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) ?
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);
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With