I was having trouble getting com.sun.jna.Structure
to work, so I tried copying the first JNA test I found and I can't even get that to work.
For convenience, try it online.
import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;
public class MyClass {
public void testSimpleSize() throws Exception {
class TestStructure extends Structure {
public int field;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("field");
}
}
Structure s = new TestStructure();
//assertEquals("Wrong size", 4, s.size());
}
public static void main(String[] args)
{
try
{
new MyClass().testSimpleSize();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
The code compiles ok, but when running I get
Exception in thread "main" java.lang.Error: Exception reading field 'field' in class MyClass$1TestStructure
at com.sun.jna.Structure.getFieldValue(Structure.java:639)
at com.sun.jna.Structure.deriveLayout(Structure.java:1285)
at com.sun.jna.Structure.calculateSize(Structure.java:1159)
at com.sun.jna.Structure.calculateSize(Structure.java:1111)
at com.sun.jna.Structure.allocateMemory(Structure.java:414)
at com.sun.jna.Structure.<init>(Structure.java:205)
at com.sun.jna.Structure.<init>(Structure.java:193)
at com.sun.jna.Structure.<init>(Structure.java:180)
at com.sun.jna.Structure.<init>(Structure.java:172)
at MyClass$1TestStructure.<init>(MyClass.java:8)
at MyClass.testSimpleSize(MyClass.java:15)
at MyClass.main(MyClass.java:23)
Caused by: java.lang.IllegalAccessException: class com.sun.jna.Structure cannot access a member of class MyClass$1TestStructure with modifiers "public"
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591)
at java.base/java.lang.reflect.Field.checkAccess(Field.java:1075)
at java.base/java.lang.reflect.Field.get(Field.java:416)
at com.sun.jna.Structure.getFieldValue(Structure.java:636)
... 11 more
Am I missing something?
As you've discovered in your answer, the root cause of the problem (as indicated by the stack trace) was lack of reflective access to your class. While your answer solves your specific issue, I wanted to expand on more possible reasons this could occur, which may help others.
The reason the JNA test case you linked to works is because the test resides in the same package as the Structure class, which gives the Structure
class access to package private classes. In your case, the inner class TestStructure
does not have the public
modifier, and resides in a different package than com.sun.jna.Structure
.
You solved the problem by moving the class to an accessible location, which works. Most often in JNA implementations, structures are declared in interfaces (and thus are by default public
).
A second possibility of getting this error is if you are using Java Modules (JPMS). Java Modules do not permit reflective access by default, so it must be explicitly allowed in the module-info.java
class, either with opens your.package to com.sun.jna;
(to allow runtime-only reflection including private members) or exports your.package to com.sun.jna;
(to allow compile-time and run-time public access). While this does not apply in your case (you're using the default package which would be in the unnamed module) this may be something you may encounter in the future if you create a modular project.