This page contains an archived post to the Design Forum (formerly called the Flexible Java Forum) made prior to February 25, 2002.
If you wish to participate in discussions, please visit the new
Artima Forums.
Message:
magic in garbage collector
Posted by wouter van der meiden on August 10, 2001 at 6:41 AM
> I'm studying to take the SCJP2 exam and ran into an interesting (I think) question. Only sublclasses and classes in the same package are supposed to be able to call a protected method, so how does the Java Garbage Collector call finalize when the signature is "protected finalize() throws Throwable"? since JDK 1.2 it is possible to call private or protected methods through the reflection api. Example code: import java.lang.reflect.Method;
class UnProtected { private static void run() { System.out.println("hello, i am private"); } } public class NoEncaps { public static void main(String[] args) throws Exception { Class clazz = Class.forName("UnProtected"); // 1 Method m = clazz.getDeclaredMethod("run", null); // 2 m.setAccessible(true); // 3 m.invoke(null, null); // 4 } } when running $ java NoEncaps class Unprotected will be loaded into the JVM (line 1) and all the information from the bytecode in file "Unprotected.class" is accessable through an object of type Class, referred to by reference clazz. E.g, in line 2 we ask for a method called "run" with an empty argument list and get a reference m. Also for private methods, such a refernce is returned.
Retrieving information about a class from within a java program through its Clazz object is a technique called reflection. In JDK 1.1, we can not abuse such method references to invoke private methods: access is still checked at the moment of method invocation and a java.lang.IllegalAccessException occurs. In JDK 1.2, we may call m.setAccessible(true), which turns this check off. In JDK 1.2 this works for applications that do not have a security manager. When running an application with the default securitymanager, the call to m.setAccessible is not allowed java -Djava.security.manager NoEncaps will result in a java.lang.reflect.ReflectPermission permission to call m.setAccessable can be switched on in a security policy file // NoEncaps.policy grant { permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; }; run java -Djava.security.manager -Djava.security.policy=NoEncaps.policy NoEncaps and the call to m.setAccessible() is allowed and therefor invocation of the method m refers to is possible again. another example of where such magic is used is serialization. when you want to write (a binary representation of) an object to file, and you want to do that in a specific way, you need to implement private methods that will be called by some generic 'write a binary representation'-algorithm. In JDK 1.1 you had to bypass javas protections in C, through the Java Native Interface (JNI). Since JDK 1.2 you can do the magic with reflection, staying within the java language proper.
Replies:
|