【问题标题】:JDK 17 Foreign memory API throws exception - Method threw 'java.lang.UnsatisfiedLinkError' exceptionJDK 17 外存 API 引发异常 - 方法引发“java.lang.UnsatisfiedLinkError”异常
【发布时间】:2021-12-12 19:47:34
【问题描述】:

我正在尝试使用 JDK 17.0.1 执行以下代码。我已确保 JDK 17 在类路径上。

这是我正在执行的代码:

import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryHandles;
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.ResourceScope;


import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;

public class PanamaMain {
    public static void main (String[] args) {
        MemoryAddress address = MemorySegment.allocateNative(4, ResourceScope.newImplicitScope()).address();

        VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());

        int value = (int) handle.get(address); //This line throws the exception mentioned above.

        System.out.println("Memory Value: " + value);
    }
}

异常原因是:java.lang.UnsatisfiedLinkError: 'java.lang.Object java.lang.invoke.VarHandle.get(java.lang.Object[])'

异常详情

我看到一些关于类似异常的回复,建议使用java.library.path 系统属性,但我收到一个错误,指出java.library.path 是无效标志。

非常感谢您在此问题上的帮助/提示!提前感谢您的宝贵时间!

【问题讨论】:

标签: java memory native unsatisfiedlinkerror


【解决方案1】:

VarHandle.get 方法需要 MemorySegment(不是 MemoryAddress)和段内的字节偏移量。标准 C 类型的布局可在 CLinker.C_XXX 中找到,因此您无需将 int 的字节大小硬编码为 4。

假设您的 PATH 对于启动 JDK17 是正确的,那么这应该可以:

MemorySegment segment = MemorySegment.allocateNative(CLinker.C_INT, ResourceScope.newImplicitScope());
VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
handle.set(segment, 0, 4567);
int value = (int)handle.get(segment, 0);
System.out.println("Memory Value: " + value + " = 0x"+Integer.toHexString(value));

打印:

Memory Value: 4567 = 0x11d7

在 JDK17 中,您还可以使用 MemoryAccess 从分配的 MemorySegment 中设置或获取值。 ,并且可以更改为:

MemorySegment segment = MemorySegment.allocateNative(CLinker.C_INT, ResourceScope.newImplicitScope());
MemoryAccess.setInt(segment, -1234);
int value = MemoryAccess.getInt(segment);
System.out.println("Memory Value: " + value + " = 0x"+Integer.toHexString(value));

打印

Memory Value: -1234 = 0xfffffb2e

注意API发生了变化,所以JDK18+中的等效代码会有所不同。

【讨论】:

  • 非常感谢您的解决方案!!它确实对我有用!我试图检查 VarHandle 上的 get 方法,看起来像。 ` public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate Object get(Object... args);`。我在那里看不到实施!这是抽象类。想知道您是如何发现它期待的是 MemorySegment 而不是 MemoryAdderss?
  • 如果你只尝试handle.get(address),它应该会给出异常:WrongMethodTypeException: cannot convert MethodHandle(VarHandle,MemorySegment,long)int to (VarHandle,MemoryAddress)Object,所以表示传递了错误类型的参数并且也省略了预期的,long参数。
猜你喜欢
  • 1970-01-01
  • 2012-02-11
  • 2015-06-14
  • 1970-01-01
  • 2014-10-25
  • 2012-01-06
  • 2020-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多