MemoryLayout::varHandle 通过可变数组进行结构化的问题

jdr*_*gon 1 java project-panama java-21

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

代码片段如下。

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;
}
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

connot convert MethodHandle(VarHandle,MemorySegment,long,int)void to (VarHandle,Object[])void

这就是我的调试所说的,我想要实现的是 varHandler.set(segment, (long)i, i);

我可以实现我的想法吗?我该怎么做?

Jor*_*nee 5

您不能Object[]直接传递持有坐标VarHandle::set(因为它是签名多态方法)。

但是,您可以使用以下命令将 var 句柄转换为方法句柄toMethodHandle,然后使用invokeWithArguments

MethodHandle setter = varHandle.toMethodHandle(VarHandle.AccessMode.SET);
setter.invokeWithArguments(varParams);
Run Code Online (Sandbox Code Playgroud)