java [jdk21][Foreign Function & Memory API]MemoryLayout::varHandle通过可变数组进行结构化的问题

wtlkbnrh  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(98)

当使用MemoryLayout::varHandle构造varHandle时,我传入了一个自组装的Object数组来实现构造MemorySegment的公共方法。但我发现它似乎阻止我使用Object数组而不是可变数组。
代码片段如下。

public static MemorySegment buildMemorySegment(Object object, MemorySegment memorySegment, MemoryLayout originMemoryLayout, MemoryLayout memoryLayout, List<PathElement> pathElements, List<Object> indexParams) throws NoSuchFieldException, IllegalAccessException {
    Class<?> aClass = object.getClass();
    if (memoryLayout instanceof SequenceLayout sequenceLayout) {
        pathElements.add(PathElement.sequenceElement());
        for (int i = 0; i < sequenceLayout.elementCount(); i++) {
            Object[] array;
            if (Collection.class.isAssignableFrom(aClass)) {
                assert object instanceof Collection<?>;
                Collection<?> collection = (Collection<?>) object;
                array = collection.toArray();
            } else {
                assert object instanceof Object[];
                array = ((Object[]) object);
            }
            Object o = array[i];
            indexParams.add((long) i);
            buildMemorySegment(o, memorySegment, originMemoryLayout, sequenceLayout.elementLayout(), pathElements, indexParams);
            indexParams.removeLast();
        }
        pathElements.removeLast();
    } else if (memoryLayout instanceof StructLayout structLayout) {
        List<MemoryLayout> memoryLayouts = structLayout.memberLayouts();
        for (MemoryLayout layout : memoryLayouts) {
            String layoutName = layout.name().orElseThrow();
            pathElements.add(PathElement.groupElement(layoutName));
            Field declaredField = aClass.getDeclaredField(layoutName);
            Object fieldValue = getFieldValue(object, declaredField);
            buildMemorySegment(fieldValue, memorySegment, originMemoryLayout, layout, pathElements, indexParams);
            pathElements.removeLast();
        }
    } else if (memoryLayout instanceof ValueLayout) {
        Object[] varParams = new Object[indexParams.size() + 2];
        varParams[0] = memorySegment;
        for (int i = 0; i < indexParams.size(); i++) {
            varParams[i + 1] = indexParams.get(i);
        }
        varParams[varParams.length - 1] = object;
        VarHandle varHandle = originMemoryLayout.varHandle(pathElements.toArray(new PathElement[0]));
        varHandle.set(varParams);
    }
    return MemorySegment.NULL;
}

关键问题是我成功地构建了MemoryLayout,并通过解析MemoryLayout来控制varHandle参数,从而构造了varHandle。出现以下问题。

这是我的调试程序所显示的,我想实现的是varHandler.set(segment, (long)i, i);
我能实现我的想法吗?我该怎么做?

ki0zmccv

ki0zmccv1#

你不能直接将保存坐标的Object[]传递给VarHandle::set(因为它是一个签名多态方法)。
但是,您可以使用toMethodHandle将var句柄转换为方法句柄,然后使用invokeWithArguments

MethodHandle setter = varHandle.toMethodHandle(VarHandle.AccessMode.SET);
setter.invokeWithArguments(varParams);

相关问题