質問

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?

役に立ちましたか?

解決 2

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.

他のヒント

Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.

The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.

The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)

The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.

  1. there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
  2. everyone could access the Class instances, but the fields are protected.
  3. in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
  4. i dont think so.
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top