If you are writing java code and adding private member variables in the hope that no one shall be able to access these member variables then reflection can surprise you. The purpose of private member variables is to set the scope which is visible to the current entity only. But with the use of reflection, we can easily change the access level of private member variables and methods and then access or modify them.

In this tutorial, we shall first see how to access private member variables and methods using reflection and then see how to stop access to them.

Accessing private members using reflection

The following code shows how to access private member variables and methods in Java.

Foo.java

package com.example;

public class Foo{
	private int a = 10;

	private void m() {
		System.out.println("this is private method from class Foo");
	}
}

Bar.java

package com.example;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Bar {

	  public static void main(String[] args) throws ReflectiveOperationException {
	    Foo foo = Foo.class.newInstance();

	    Class<Foo> clazz = Foo.class;
	    
	    Method[] methods = clazz.getDeclaredMethods();
	    for (int i = 0; i < methods.length; i++) {
	    	 methods[i].setAccessible(true);
	    	 methods[i].invoke(foo);
		}
	    
	    Field[] fields = clazz.getDeclaredFields();
	    for (int i = 0; i < fields.length; i++) {
	    	fields[i].setAccessible(true);
	    	fields[i].setInt(foo,1);
	    	System.out.println(fields[i].getInt(foo));
		}
	  }
}

Output:

this is private method from class Foo
1

In the above code, the member variable a and method m both are private but by using reflection, there access level has been changes to true and hence are accessible through reflection. The output shows how the private member variables have been accessed.

Note that these private members are still not visible and accessible to classes other than Foo.

Preventing access to private member using reflection

There are two ways for stopping access to private member methods. These methods disallow the access to the methods even using reflection. While the first method is only applicable for methods, the other method is applicable for both member variables and methods.

1. Adding code in private method

The following changes are required in the method “m” in Foo class:

package com.example;

import java.lang.reflect.ReflectPermission;
import java.security.AccessController;

public class Foo{
	private int a = 10;

	private void m() {
		ReflectPermission perm = new ReflectPermission("suppressAccessChecks", "");
	    	AccessController.checkPermission(perm);
		System.out.println("this is private method from class Foo");
	}
}

Output:

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 com.example.Bar.main(Bar.java:16)
Caused by: java.security.AccessControlException: access denied (“java.lang.reflect.ReflectPermission” “suppressAccessChecks”)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
at java.security.AccessController.checkPermission(AccessController.java:555)
at com.example.Foo.m(Foo.java:11)
… 5 more

In the code shown above, the permissions for accessing the current method are set as disallowed and hence the exception when trying to invoke the method from main method in Bar class.

2. Adding custom security manager code

The default implementation of security manager allows private member access using reflection. However we can write our security manager and then apply it in the current application. The only thing we want to do in custom security manager is to disallow the access to private members of the class through reflection.

The following code shows how to create a new security manager which extends from the SecurityManager class and overrides the “checkPermission” method.

Foo.java

package com.example;

import java.security.Permission;

public class Foo{
	static{
		try {
			System.setSecurityManager(new MySecurityManager());
		} catch (SecurityException se) {
			System.out.println("SecurityManager already set!");
		}
	}

	private int a = 10;

	private void m() {
		System.out.println("this is private method from class Foo");
	}
}

class MySecurityManager extends SecurityManager {
	public void checkPermission(Permission perm) {
		if(perm.getName().equals("suppressAccessChecks")){
			throw new SecurityException("Can not change the permission.");
		}
	}
}

Bar.java

package com.example;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.Permission;

public class Bar {

	public static void main(String[] args) throws ReflectiveOperationException {
		Foo foo = Foo.class.newInstance();

		Class<Foo> clazz = Foo.class;

		Method[] methods = clazz.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			methods[i].setAccessible(true);
			methods[i].invoke(foo);
		}

		Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			fields[i].setAccessible(true);
			fields[i].setInt(foo,1);
			System.out.println(fields[i].getInt(foo));
		}
	}
}

The output after executing the above program is:

Exception in thread “main” java.lang.SecurityException: Can not change the permission.
at com.example.MySecurityManager.checkPermission(Foo.java:24)
at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:128)
at com.example.Bar.main(Bar.java:16)

In the code in Foo class, we are assigning the “MySecurityManager” as default which is blocking the access to private method as well variable.

Related Posts

Accessing and Preventing access to private members using reflection admin Core Java
If you are writing java code and adding private member variables in the hope that no one shall be able to access these member variables then reflection can surprise you. The purpose of private member variables is to set the scope which is visible to the current entity only....
If you are writing java code and adding private member variables in the hope that no one shall be able to access these member variables then reflection can surprise you. The purpose of private member variables is to set the scope which is visible to the current entity only. But with the use of reflection, we can easily change the <a href="http://www.javaexperience.com/eclipse-get-access-modifier-suggestions-using-ucdetector-plugin/" title="Get access modifier suggestions using Eclipse ucdetector plugin">access level</a> of private member variables and methods and then access or modify them. In this tutorial, we shall first see how to access private member variables and methods using reflection and then see how to stop access to them. <h2>Accessing private members using reflection</h2> The following code shows how to access private member variables and methods in Java. <strong>Foo.java</strong> 1 <strong>Bar.java</strong> 1 Output: <blockquote> this is private method from class Foo 1 </blockquote> In the above code, the member variable a and method m both are private but by using reflection, there access level has been changes to true and hence are accessible through reflection. The output shows how the private member variables have been accessed. Note that these private members are still not visible and accessible to classes other than Foo. <h2>Preventing access to private member using reflection</h2> There are two ways for stopping access to private member methods. These methods disallow the access to the methods even using reflection. While the first method is only applicable for methods, the other method is applicable for both member variables and methods. <h3>1. Adding code in private method</h3> The following changes are required in the method "m" in Foo class: 1 Output: <blockquote> 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 com.example.Bar.main(Bar.java:16) Caused by: java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks") at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366) at java.security.AccessController.checkPermission(AccessController.java:555) at com.example.Foo.m(Foo.java:11) ... 5 more </blockquote> In the code shown above, the permissions for accessing the current method are set as disallowed and hence the exception when trying to invoke the method from <a href="http://www.javaexperience.com/main-method-in-java/" title="How main Method works in Java">main method</a> in Bar class. <h3>2. Adding custom security manager code</h3> The default implementation of security manager allows private member access using reflection. However we can write our security manager and then apply it in the current application. The only thing we want to do in custom security manager is to disallow the access to private members of the class through reflection. The following code shows how to create a new security manager which extends from the SecurityManager class and overrides the "checkPermission" method. <strong>Foo.java</strong> 1 <strong>Bar.java</strong> 1 The output after executing the above program is: <blockquote> Exception in thread "main" java.lang.SecurityException: Can not change the permission. at com.example.MySecurityManager.checkPermission(Foo.java:24) at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:128) at com.example.Bar.main(Bar.java:16) </blockquote> In the code in Foo class, we are assigning the "MySecurityManager" as default which is blocking the access to private method as well variable.
Differences between StringBuilder and StringBuffer in Java
Signing JAR file with certificate and verification
The following two tabs change content below.
I run this blog with lots of passion. In this website, you will find tutorials on Core Java, Spring, Struts, Web Applications, Portals and Database. Please support me and the website by sharing the posts on your facebook / twitter. You can tap the share button at the top of each post. Thanks for the support.

Comments

comments