javareflectionclass-visibility

Different behaviour of Class literal and Class.forName for package local classes


Only for example lets consider the class ClassFileAssembler from the sun.reflect package.

This class is a package local class:

class ClassFileAssembler implements sun.reflect.ClassFileConstants {...

So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.

However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.

If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?

Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;

Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.

However we still able to get the ClassFileAssembler class object:

Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");

It works fine and gives us a full class description.


So, the questions are:

1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?

2) Why do they have such different security checks?

3) What's the reason to protect .class reference in such way?

4) Do these techniques use different class loaders?


Solution

  • If you check the javadoc of Class#forName, you will see that:

    Note that this method does not check whether the requested class is accessible to its caller.