Access package-private variables using reserved package name

时光毁灭记忆、已成空白 提交于 2019-12-13 14:22:31

问题


I was studying the source code of java.util.HashMap and I wanted to see how well the hashcode function distributes the key's in the internal array of Entry's(which is a package private variable).So I made a package named java.util in my project just to check weather I can fool the compiler to think it's the same package.Surprisingly it worked and I wrote the following code:

package java.util;

public class HashMapExt<K, V> extends HashMap<K, V> implements Map<K, V> {

    public static void main(String[] args) {
        HashMapExt<Integer, String> mp = new HashMapExt<Integer, String>();
        mp.put(1, "Hello");
        mp.put(2, "Map");
        mp.put(3, "Extention");
        mp.printData();
    }

    void printData() {

        System.out.println(Arrays.toString(table));
    }
}

It compiled successfully but while running it gave an exception:

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.util
    at java.lang.ClassLoader.preDefineClass(Unknown Source)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$000(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)

Now the question is, is it possible to change the default security model so that I can access the internal variable table or is there any other alternative (maybe by using reflection) ?


回答1:


Even if there is an option to have your class in the java.util package (like replacing the core jar or defining your custom class loader for example), you'd better use reflection. It is simple and straightforward:

Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Map.Entry[] entries = (Map.Entry[]) tableField.get(yourMap);



回答2:


You may try either prepending your jar in the classpath or by using an endorsed directory.

The former:

java -Xbootclasspath/p:youJarHere.jar  ..... 

And the effect is, to load first the classes you have in yourJar, even overriding core classes.

The later form is to place in your $JAVA_HOME/lib/endorsed directory the classes/jars, it has a similar effect.

I haven't used any of these for a couple of years, but I used them once to replace a core class ( something in the CORBA package or something like that ).

Give it a try and let us know if it worked.

Here some links:

http://blogs.sourceallies.com/2010/02/replacing-and-patching-java-application-and-core-classes/

http://download.oracle.com/javase/6/docs/technotes/guides/standards/



来源:https://stackoverflow.com/questions/4224760/access-package-private-variables-using-reserved-package-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!