如何通过反射访问私有方法和私有数据成员?

Eng*_*uad 26 java security reflection private

我知道我们可以通过反射来访问私有构造函数@Sanjay T. Sharma在他的问题回答中提到:"instanceof Void"总是返回false吗?

但是,@ duffymo :

你可以使用反射访问私有 - 方法,构造函数,数据成员,一切.

  1. 如何访问私有方法和私有数据成员?
  2. 是否可以通过反射访问局部变量?
  3. 有没有办法阻止任何人访问私有构造函数,方法和数据成员?

Psh*_*emo 69

1)如何访问私有方法和私有数据成员?

你可以在setAccessible(true)方法的帮助下做到这一点:

class Dummy{
    private void foo(){
        System.out.println("hello foo()");
    }
    private int i = 10;
}

class Test{
    public static void main(String[] args) throws Exception {
        Dummy d = new Dummy();

        /*---  [INVOKING PRIVATE METHOD]  ---*/
        Method m = Dummy.class.getDeclaredMethod("foo");
        //m.invoke(d); // Exception java.lang.IllegalAccessException
        m.setAccessible(true);//Abracadabra
        m.invoke(d); // Now it's OK

        /*---  [GETING VALUE FROM PRIVATE FIELD]  ---*/
        Field f = Dummy.class.getDeclaredField("i");
        //System.out.println(f.get(d)); // Not accessible now
        f.setAccessible(true); // Abracadabra
        System.out.println(f.get(d)); // Now it's OK

        /*---  [SETTING VALUE OF PRIVATE FIELD]  ---*/
        Field f2 = Dummy.class.getDeclaredField("i");
        //f2.set(d,20); // Not accessible now
        f2.setAccessible(true); // Abracadabra
        f2.set(d, 20); // Now it's OK
        System.out.println(f2.get(d));
    }
}
Run Code Online (Sandbox Code Playgroud)

2)是否可以通过反射访问局部变量?

不能.局部变量不能在创建它们的块之外访问(有人可以说你可以将这样的变量分配给一个字段field = localVariable;,然后通过反射访问这样一个字段,但这样我们将访问该,不是变量).

3)有没有办法阻止任何人访问私有构造函数,方法和数据成员?

我认为constructors或者methods您可以使用stacktrace来检查它是否被调用Reflection.
对于字段,我找不到阻止通过反射访问它们的解决方案.

[警告:未经任何人批准.我只是根据你的问题写了它.]

class Dummy {
    private void safeMethod() {
        StackTraceElement[] st = new Exception().getStackTrace();
        // If a method was invoked by reflection, the stack trace would be similar
        // to something like this:
        /*
        java.lang.Exception
            at package1.b.Dummy.safeMethod(SomeClass.java:38)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        ->    at java.lang.reflect.Method.invoke(Method.java:601)
            at package1.b.Test.main(SomeClass.java:65)
        */
        //5th line marked by "->" is interesting one so I will try to use that info

        if (st.length > 5 &&
            st[4].getClassName().equals("java.lang.reflect.Method"))
            throw new RuntimeException("safeMethod() is accessible only by Dummy object");

        // Now normal code of method
        System.out.println("code of safe method");
    }

    // I will check if it is possible to normally use that method inside this class
    public void trySafeMethod(){
        safeMethod();
    }

    Dummy() {
        safeMethod();
    }
}

class Dummy1 extends Dummy {}

class Test {
    public static void main(String[] args) throws Exception {
        Dummy1 d1 = new Dummy1(); // safeMethod can be invoked inside a superclass constructor
        d1.trySafeMethod(); // safeMethod can be invoked inside other Dummy class methods
        System.out.println("-------------------");

        // Let's check if it is possible to invoke it via reflection
        Method m2 = Dummy.class.getDeclaredMethod("safeMethod");
        // m.invoke(d);//exception java.lang.IllegalAccessException
        m2.setAccessible(true);
        m2.invoke(d1);
    }
}
Run Code Online (Sandbox Code Playgroud)

Test主方法输出:

code of safe method
code of safe method
-------------------
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at package1.b.Test.main(MyClass2.java:87)
Caused by: java.lang.RuntimeException: method safeMethod() is accessible only by Dummy object
    at package1.b.Dummy.safeMethod(MyClass2.java:54)
    ... 5 more
Run Code Online (Sandbox Code Playgroud)


JB *_*zet 9

  1. 使用您链接到的答案中显示的方法:setAccessible(true),它是Field,Constructor和Method的超类的方法.
  2. 没有.
  3. 不,除非代码在您控制的JVM中运行,否则您将在其中安装安全管理器.但是如果你给某人一个jar文件,并且他使用这个jar文件中的类,他将能够访问所有内容.

  • 我不认为这是针对Java的.您无法保护运行它的用户的"您的"代码.DRM实施也在努力解决这个问题.远程执行(SaaS)可能是唯一的"解决方案".无论哪种方式,隐藏在OOP中的信息不是保密的安全功能,但程序员不必看到并且不小心搞乱实现内部的便利. (13认同)