Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access package-private variables using reserved package name

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) ?

like image 813
Emil Avatar asked Feb 26 '23 19:02

Emil


2 Answers

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);
like image 110
Bozho Avatar answered Mar 15 '23 09:03

Bozho


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/

like image 32
OscarRyz Avatar answered Mar 15 '23 10:03

OscarRyz