java - 如何通过反射访问私有(private)方法和私有(private)数据成员?

标签 java security reflection private

我知道我们可以通过反射访问私有(private)构造函数 @Sanjay T. Sharma他在回答我的问题时提到:Does “instanceof Void” always return false?

但是,@duffymo said :

you can access private everything with reflection - methods, constructors, data members, everything.

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

最佳答案

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

你可以在 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));
    }
}

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

没有。局部变量不能在创建它们的 block 之外访问(有人可能会说您可以将这样的变量分配给像 field = localVariable; 这样的字段,然后通过反射访问这样的字段,但是这样我们将访问,而不是变量)。

3) 有什么方法可以阻止任何人访问私有(private)构造函数、方法和数据成员?

我认为对于 constructorsmethods,您可以使用 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);
    }
}

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

关于java - 如何通过反射访问私有(private)方法和私有(private)数据成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11483647/

相关文章:

java - 无法使用反射访问 @ConfigurationProperties 类的变量?

java - Matcher.Find() 在应该为 true 时返回 false

java - 通过Java Mongo 3.4驱动程序或Spring Data Mongo访问currentOp

security - 为cordova 混合移动应用程序选择哪种Google Oauth 2.0 客户端ID 类型?

Java Web Start Sign 库 Jars

c# - 创建未知类型的数组。 C#

c# - 对列表和打印值的反射(reflection)

java - 在 Java 中获取系统的 MAC 地址

JAVA 无法向 arrayList 添加多个对象

android - Proguarding Android 应用程序——它有多重要(尤其是与应用程序内支付相关的)