简体   繁体   English

实例化 JNA 结构的子类抛出 IllegalAccessException

[英]Instantiating subclass of JNA Structure throws IllegalAccessException

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.我无法com.sun.jna.Structure工作,所以我尝试复制我找到的第一个 JNA 测试,但我什至无法让它工作。

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?我错过了什么吗?

I have found a solution and it was much simpler than I thought.我找到了一个解决方案,它比我想象的要简单得多。

According to the documentation ,根据文件

An IllegalAccessException is thrown when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor.当应用程序尝试反射式地创建实例(不是数组)、设置或获取字段或调用方法时,抛出 IllegalAccessException,但当前执行的方法无权访问指定 class 的定义,字段,方法或构造函数。

Which means that com.sun.jna.Structure needs to have access to TestStructure , in order to use reflection (which it needs in order to get the struct fields).这意味着com.sun.jna.Structure需要访问TestStructure ,才能使用反射(它需要它来获取结构字段)。 The simplest way to solve that is to move TestStructure out of the function and make it public.解决这个问题的最简单方法是将TestStructure从 function 中移出并公开。 Like this:像这样:


import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;

public class MyClass {
    public class TestStructure extends Structure {
        public int field;
        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("field");
        }
    }
    
    public void testSimpleSize() throws Exception {
        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);
        }
    }
}

There may be a better solution, but this is the simplest and works for me.可能有更好的解决方案,但这是最简单的,对我有用。

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.正如您在回答中发现的那样,问题的根本原因(如堆栈跟踪所示)是缺乏对 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. 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 .在您的情况下,内部 class TestStructure没有public修饰符,并且与 com.sun.jna.Structure 位于不同的com.sun.jna.Structure

You solved the problem by moving the class to an accessible location, which works.您通过将 class 移动到可访问的位置解决了该问题,该位置有效。 Most often in JNA implementations, structures are declared in interfaces (and thus are by default public ).大多数情况下,在 JNA 实现中,结构是在接口中声明的(因此默认情况下是public )。

A second possibility of getting this error is if you are using Java Modules (JPMS).出现此错误的第二种可能性是您使用的是 Java 模块 (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; 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; (以允许仅包含私有成员的运行时反射)或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.虽然这不适用于您的情况(您使用的是默认的 package,它将位于未命名的模块中),如果您创建模块化项目,这可能是您将来可能遇到的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM