我正在研究java.util.HashMap
的源代码,我想看看哈希码函数在Entry
的内部数组中分配密钥的效果如何(是一个包私有变量)。所以我在我的项目中创建了一个名为java.util
的包只是为了检查天气我可以欺骗编译器认为它是相同的包。令人惊讶的是它有效并且我编写了以下代码:
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));
}
}
它已成功编译但在运行时它给出了一个例外:
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)
现在问题是,是否可以更改默认安全模型以便我可以访问内部变量table
或者是否有其他替代方法(可能使用反射)?
答案 0 :(得分:6)
即使有一个选项让你的类在java.util
包中(例如替换核心jar或定义你的自定义类加载器),你最好使用反射。它简单明了:
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Map.Entry[] entries = (Map.Entry[]) tableField.get(yourMap);
答案 1 :(得分:2)
您可以尝试使用背书目录在类路径中预先设置jar或。
前者:
java -Xbootclasspath/p:youJarHere.jar .....
效果是,首先加载你在theJar中的类,甚至覆盖核心类。
后面的表格是在您的$JAVA_HOME/lib/endorsed
目录中放置类/罐子,它具有类似的效果。 击>
我几年没有使用过这些,但是我用它们一次来替换核心类(CORBA包中的东西或类似的东西)。
尝试一下,让我们知道它是否有效。
这里有一些链接:
http://blogs.sourceallies.com/2010/02/replacing-and-patching-java-application-and-core-classes/
http://download.oracle.com/javase/6/docs/technotes/guides/standards/