Доступ к закрытым переменным пакета, используя зарезервированное имя пакета - PullRequest
3 голосов
/ 19 ноября 2010

Я изучал исходный код 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 илиЕсть ли другая альтернатива (, возможно, с использованием отражения )?

Ответы [ 2 ]

6 голосов
/ 19 ноября 2010

Даже если есть возможность включить ваш класс в пакет java.util (например, заменить основной jar или определить свой загрузчик классов), вам лучше использовать отражение.Это просто и понятно:

Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Map.Entry[] entries = (Map.Entry[]) tableField.get(yourMap);
2 голосов
/ 19 ноября 2010

Вы можете попытаться либо добавить jar в classpath, либо , используя одобренный каталог .

Бывший:

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

В результате вы сначала загружаете классы, которые есть в вашем Jar, даже переопределяя базовые классы.

Более поздняя форма должна поместить в ваш каталог $JAVA_HOME/lib/endorsed классы / jars, это имеет аналогичный эффект.

Я не использовал ни одного из них в течение нескольких лет, но я использовал их один раз для замены основного класса (что-то в пакете 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...