I'm trying to execute the following code using JDK 17.0.1. I have ensured the JDK 17 is on the class path.
Here is the code i'm executing:
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);
}
}
The cause of the exception is: java.lang.UnsatisfiedLinkError: 'java.lang.Object java.lang.invoke.VarHandle.get(java.lang.Object[])'
I saw some replies on a similar exception suggesting using the java.library.path
system property but I got an error that the java.library.path
is an invalid flag.
I would appreciate your help/tips on this issue! Thank you in advance for your time!
The VarHandle.get
method is expecting a MemorySegment
(not MemoryAddress
) and offset in bytes within the segment. The layouts of standard C types are found in CLinker.C_XXX
so you don't need to hardcode byte size of int
as 4.
Assuming that your PATH is correct for launching JDK17 then this should work:
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));
Prints:
Memory Value: 4567 = 0x11d7
In JDK17 you can also use MemoryAccess
to set or get values from allocated MemorySegment
. , and could change to:
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));
Prints
Memory Value: -1234 = 0xfffffb2e
Note that the API has changed, so the equivalent code in JDK18+ will be different.