Как получить доступ к частным методам и частным данным через reflection?

Я знаю, что мы можем получить доступ к частному конструктору посредством отражения, как @Sanjay Т. Шарма упомянул в своем ответе на мой вопрос: всегда ли «instanceof Void» возвращает false?

Однако, @duffymo сказал :

вы можете получить доступ к частному все с помощью отражений – методов, конструкторов, членов данных, всего.

  1. Как я могу получить доступ к частным методам и частным данным?
  2. Можно ли получить доступ к локальной переменной через reflection?
  3. Есть ли способ предотвратить доступ любого пользователя к частным конструкторам, методам и членам данных?

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)); } } 

2) Можно ли получить доступ к локальной переменной посредством отражения?

Нет. Локальные переменные не могут быть доступны за пределами блока, в котором они были созданы (кто-то может сказать, что вы можете назначить такую ​​переменную полю, например field = localVariable; и позже получить доступ к такому полю через reflection, но таким образом мы будем доступ к значению , а не переменной ).

3) Есть ли способ предотвратить доступ любого пользователя к частным конструкторам, методам и членам данных?

Я думаю, что для constructors или methods вы можете использовать stacktrace, чтобы проверить, был ли он вызван Reflection .
Для полей я не могу найти решение для предотвращения доступа к ним через 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 
  1. Используя метод, указанный в ответе, к которому вы привязались : setAccessible (true) , который является методом суперclassа поля, конструктора и метода.
  2. Нет.
  3. Нет, если код не работает в JVM, который вы контролируете, где вы устанавливаете менеджера безопасности. Но если вы дадите кому-нибудь файл jar, и он использует classы из этого файла jar, он сможет получить доступ ко всему.

Чтобы получить доступ к приватному полю, вам необходимо вызвать Class.getDeclaredField(String name) или enter code here . Проверьте этот простой код:

 public class PrivateObject { private String privateString = null; public PrivateObject(String privateString) { this.privateString = privateString; } } PrivateObject privateObject = new PrivateObject("The Private Value"); Field privateStringField = PrivateObject.class. getDeclaredField("privateString"); privateStringField.setAccessible(true); String fieldValue = (String) privateStringField.get(privateObject); System.out.println("fieldValue = " + fieldValue 

Чтобы получить доступ к приватному методу, вам необходимо вызвать Class.getDeclaredMethod (String name, Class [] parameterTypes) или Class.getDeclaredMethods ().

Проверьте этот простой код:

 public class PrivateObject { private String privateString = null; public PrivateObject(String privateString) { this.privateString = privateString; } private String getPrivateString(){ return this.privateString; } } PrivateObject privateObject = new PrivateObject("The Private Value"); Method privateStringMethod = PrivateObject.class. getDeclaredMethod("getPrivateString", null); privateStringMethod.setAccessible(true); String returnValue = (String) privateStringMethod.invoke(privateObject, null); System.out.println("returnValue = " + returnValue); 

Подробнее читайте на странице http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html.

  Area s=(Area)c.newInstance(); s.setRadius(10); System.out.println("Area: "+s.calculateArea(4)); Method m[]=c.getDeclaredMethods(); Constructor c1[]=c.getConstructors(); for(int i=0;i 

Пример, как показано ниже:

 import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class Test { private int a = 5; // Private data member private void call(int n) // Private method { System.out.println("in call() n: " + n); } } public class Sample { public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class c = Class.forName("Test"); Object obj = c.newInstance(); //---- Accessing a private method Method m=c.getDeclaredMethod("call",new Class[]{int.class}); m.setAccessible(true); m.invoke(obj,7); //---- Accessing a private data member Field d = c.getDeclaredField("a"); d.setAccessible(true); System.out.println(d.getInt(obj)); } } 

Чтобы ответить на третий вопрос:

  1. Есть ли способ предотвратить доступ любого пользователя к частным конструкторам, методам и членам данных?

Ответ:

Да, вы можете ограничить доступ (вы можете выбросить исключение, когда кто-то пытается получить доступ к вашему частному конструктору / методу / данным)

Обратитесь к приведенному ниже примеру:

 ******JavaSingleton Class****** package server; public class JavaSingleton { private static final JavaSingleton INSTANCE = new JavaSingleton(); private JavaSingleton() { if (INSTANCE != null) { throw new IllegalStateException("Inside JavaSingleton(): JavaSingleton " + "instance already created."); } System.out.println("Inside JavaSingleton(): Singleton instance is being created."); } public static final JavaSingleton getInstance() { return INSTANCE; } } ***Listing 2: JavaSingleton client*** import server.JavaSingleton; import java.lang.reflect.*; public class TestSingleton { public static void main(String[] args) throws ReflectiveOperationException { System.out.println("Inside main(): Getting the singleton instance using getInstance()..."); JavaSingleton s = JavaSingleton.getInstance(); System.out.println("Inside main(): Trying to use reflection to get another instance..."); Class clazz = JavaSingleton.class; Constructor cons = clazz.getDeclaredConstructor(); cons.setAccessible(true); JavaSingleton s2 = cons.newInstance(); } } Output: C:\singleton>java TestSingleton Inside main(): Getting the singleton instance using getInstance()... Inside JavaSingleton(): Singleton instance is being created. Inside main(): Trying to use reflection to get another instance... Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at TestSingleton.main(TestSingleton.java:13) Caused by: java.lang.IllegalStateException: Inside JavaSingleton(): JavaSingleton instance already created. at server.JavaSingleton.(JavaSingleton.java:7) ... 5 more 

Этот пример был для одноэлементного classа (проверка в конструкторе), но вы все равно можете реализовать эту логику для частных методов, которые вы хотите предотвратить доступ из других classов.

В этом случае вы также объявите статический экземпляр и проверите его значение в приватном методе и произнесите ошибку в случае любого нежелательного значения.

  • Разрешить Java использовать ненадежный сертификат для соединения SSL / HTTPS
  • Автоматический вход в систему и блокировка
  • Как создать изолированную среду Java?
  • Учетные записи пользователя «Slave» в GNU / Linux
  • Windows XP PRO SP3 - остановить изменения ключа ключа безопасности, установленного неизвестной программой
  • Putty 0.61: почему я вижу сообщение «Access Denied» после ввода моего идентификатора входа?
  • Каковы последствия установки installSecurityContext = «False», если я использую https?
  • Проверка подлинности зависимостей в автоматизированных системах сборки на основе Maven POM
  • разница между http.context.user и thread.currentprincipal и когда их использовать?
  • Как реализовать возможность для пользователя размещать данные в формате html в безопасном режиме?
  • Разрешить группе UNIX доступ только к одному файлу через SSH
  • Давайте будем гением компьютера.