使用反射时出现 IllegalAccessException

发布于 2024-10-20 04:31:11 字数 556 浏览 2 评论 0原文

我试图学习反射,并且遇到了这个 IllegalAccessException。请看下面的代码:

public class ReflectionTest
{
      public static void main(String[] args)
      {
           Set<String> myStr = new HashSet<String>();
           myStr.add("obj1");
           Iterator itr = myStr.iterator();
           Method mtd = itr.getClass().getMethod("hasNext");
           System.out.println(m.invoke(it));
      }
} 

当我尝试运行这个程序时,我得到以下信息:

Exception in thread "main" IllegalAccessException

我不明白发生了什么。有什么想法吗?提前致谢。

I was trying to learn reflection and I came across this IllegalAccessException. Please see the following code:

public class ReflectionTest
{
      public static void main(String[] args)
      {
           Set<String> myStr = new HashSet<String>();
           myStr.add("obj1");
           Iterator itr = myStr.iterator();
           Method mtd = itr.getClass().getMethod("hasNext");
           System.out.println(m.invoke(it));
      }
} 

When I tried to run this program, I got the following:

Exception in thread "main" IllegalAccessException

I don't understand what's going on. Any ideas? Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ペ泪落弦音 2024-10-27 04:31:11

麻烦的代码是这样的:

itr.getClass().getMethod

您可能希望在 Iterator 类上使用 hasNext 。您编写的是 HashMap.KeyIterator 类,根据 Java 语言访问说明符(或至少反射使用的 JDK 1.0 的粗略解释),该类对您的代码不可用。

改为使用:(

Iterator.class.getMethod

如果不是为了学习目的,请远离反思。)

The troublesome piece of code is this:

itr.getClass().getMethod

You probably wanted hasNext on the Iterator class. What you have written is the HashMap.KeyIterator class, which according the Java language access specifiers (or at least the rough interpretation of JDK 1.0 used by reflection) is not available to your code.

Use instead:

Iterator.class.getMethod

(And if it wasn't for learning purposes, stay away from reflection.)

对风讲故事 2024-10-27 04:31:11

您无法访问它,因为 Iterator 是私有内部类。更多说明可以在此处找到。

You cannot access it, because the Iterator is a private inner class. More explanation can be found here.

稳稳的幸福 2024-10-27 04:31:11

很明显,您当前执行的方法无法访问名为 hasNext 的方法,例如,由于它是 privateprotected< /代码>。您可以尝试使用 method.setAccessible(true); 启用对它的访问

它也可能是您有一些 在您的安全管理器中定义的限制(如果您使用例如linux可能已默认包含在发行版 java 包中)。

[编辑] 事实证明,Tom Hawtin 确定了正确的根本原因。您确实是在 HashMap.KeyIterator 上进行操作。尽管解决方案是使用 Iterator.class 而不是 itr.getClass(),但您仍然可以使用 setAccessible(true) 启用对它的访问。

It's apparent that your currently executing method does not have access to the method named hasNext, e.g., by it being private or protected. You could try to enable access to it using method.setAccessible(true);

It might also be that you have some restrictions defined in your security manager (which, if you use e.g., linux, might have been included default from the distributions java package).

[EDIT] As it turns out, Tom Hawtin identified the correct root cause. You are indeed operating on HashMap.KeyIterator. Although the solution would be to use Iterator.class instead of itr.getClass() you could still enable access to it using setAccessible(true).

爱已欠费 2024-10-27 04:31:11

我怀疑你应该使用 getDeclaredMethod (以及其他问题)。我懒得记住反射 API 详细信息(它们是供编译器使用的!),但在您的情况下,将您的代码与 生成的代码进行比较dp4j:

$ javac -Averbose=true -All -cp dp4j-1.2-SNAPSHOT-jar-with-dependencies.jar ReflectionTest.java 
ReflectionTest.java:6: Note: 
import java.util.*;

public class ReflectionTest {

public ReflectionTest() {
    super();
}

@com.dp4j.Reflect()
public static void main(String[] args) throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException, java.lang.InstantiationException, java.lang.IllegalArgumentException {
    final java.lang.reflect.Constructor hashSetConstructor = Class.forName("java.util.HashSet").getDeclaredConstructor();
    hashSetConstructor.setAccessible(true);
    Set<String> myStr = (.java.util.Set<.java.lang.String>)hashSetConstructor.newInstance();
    final java.lang.reflect.Method addWithEMethod = Class.forName("java.util.Set").getDeclaredMethod("add", .java.lang.Object.class);
    addWithEMethod.setAccessible(true);
    addWithEMethod.invoke(myStr, new .java.lang.Object[1][]{"obj1"});
    final java.lang.reflect.Method iteratorMethod = Class.forName("java.util.Set").getDeclaredMethod("iterator");
    iteratorMethod.setAccessible(true);
    Iterator itr = (.java.util.Iterator)iteratorMethod.invoke(myStr);
    final java.lang.reflect.Method hasNextMethod = Class.forName("java.util.Iterator").getDeclaredMethod("hasNext");
    hasNextMethod.setAccessible(true);
    final java.lang.reflect.Method printlnWithbooleanMethod = Class.forName("java.io.PrintStream").getDeclaredMethod("println", .java.lang.Boolean.TYPE);
    printlnWithbooleanMethod.setAccessible(true);
    printlnWithbooleanMethod.invoke(System.out, new .java.lang.Object[1][]{hasNextMethod.invoke(itr)});
}

}

    public static void main(String[] args)
                       ^
...

$ java ReflectionTest
true

您需要做的唯一更改是使用 @com.dp4j.Reflect 注释您的 main 方法:

$ vim ReflectionTest.java
import java.util.*;

public class ReflectionTest
{
        @com.dp4j.Reflect
        public static void main(String[] args)
        {
                Set<String> myStr = new HashSet<String>();
                myStr.add("obj1");
                Iterator itr = myStr.iterator();
                // Method mtd = itr.getClass().getMethod("hasNext");
                System.out.println(itr.hasNext());
        }
}

注意:这仅适用于 dp4j-1.2-SNAPSHOT (我刚刚添加了对它的支持)。如果您不使用 Maven,请从 下载 jar在这里。您可以在此处。

I suspect you should use getDeclaredMethod (among other issues). I don't bother to remember Reflection API details (they're for the compiler!), but in your case compare your code with that produced by dp4j:

$ javac -Averbose=true -All -cp dp4j-1.2-SNAPSHOT-jar-with-dependencies.jar ReflectionTest.java 
ReflectionTest.java:6: Note: 
import java.util.*;

public class ReflectionTest {

public ReflectionTest() {
    super();
}

@com.dp4j.Reflect()
public static void main(String[] args) throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException, java.lang.InstantiationException, java.lang.IllegalArgumentException {
    final java.lang.reflect.Constructor hashSetConstructor = Class.forName("java.util.HashSet").getDeclaredConstructor();
    hashSetConstructor.setAccessible(true);
    Set<String> myStr = (.java.util.Set<.java.lang.String>)hashSetConstructor.newInstance();
    final java.lang.reflect.Method addWithEMethod = Class.forName("java.util.Set").getDeclaredMethod("add", .java.lang.Object.class);
    addWithEMethod.setAccessible(true);
    addWithEMethod.invoke(myStr, new .java.lang.Object[1][]{"obj1"});
    final java.lang.reflect.Method iteratorMethod = Class.forName("java.util.Set").getDeclaredMethod("iterator");
    iteratorMethod.setAccessible(true);
    Iterator itr = (.java.util.Iterator)iteratorMethod.invoke(myStr);
    final java.lang.reflect.Method hasNextMethod = Class.forName("java.util.Iterator").getDeclaredMethod("hasNext");
    hasNextMethod.setAccessible(true);
    final java.lang.reflect.Method printlnWithbooleanMethod = Class.forName("java.io.PrintStream").getDeclaredMethod("println", .java.lang.Boolean.TYPE);
    printlnWithbooleanMethod.setAccessible(true);
    printlnWithbooleanMethod.invoke(System.out, new .java.lang.Object[1][]{hasNextMethod.invoke(itr)});
}

}

    public static void main(String[] args)
                       ^
...

$ java ReflectionTest
true

The only change you need to do is annotate your main method with @com.dp4j.Reflect:

$ vim ReflectionTest.java
import java.util.*;

public class ReflectionTest
{
        @com.dp4j.Reflect
        public static void main(String[] args)
        {
                Set<String> myStr = new HashSet<String>();
                myStr.add("obj1");
                Iterator itr = myStr.iterator();
                // Method mtd = itr.getClass().getMethod("hasNext");
                System.out.println(itr.hasNext());
        }
}

NB: this works only with dp4j-1.2-SNAPSHOT (I've just added suport for it). If you don't use Maven, download the jar from here. You find the test case with your problem here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文