java -cp path-to-lib-1.jar;path-to-lib-2.jar;path-to-directory package1.package2.ClassFoo
« Сложные интерфейсы на javascript вместе Yahoo UI. Часть 6 | Сложные интерфейсы на javascript вместе Yahoo UI. Часть 8 » |
Анализируем в java загружаемые классы
Полагаю, что те, кто профессионально занимается разработкой на java, знает что такое classpath и насколько он важен для правильной работы приложения. Когда среда выполнения java выполняет ваш код, например, такой:package foo;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.math.BigDecimal;
public class Boo {
public static void main(String[] args) {
List li =new ArrayList ();
li.add(new Date());
li.add(new BigDecimal(1000));
System.out.println("li = " + li);
}
}
Когда поступает запрос на загрузку класса, например, Number, то этот запрос проходит через цепочку специализированных объектов classloader-ов. Есть встроенные classloader-ы и есть те, которые вы можете добавлять сами, например, для загрузки классов/ресурсов из неизвестных на стадии запуска приложения источников (например, загрузка классов плагинов из jar-файлов подкладываемых в каталог plugins приложения).
Итак, есть три встроенных classloader-а, у каждого из которых есть родительский classloader (кроме первого, изначального). Когда необходимо выполнить загрузку класса, то последовательно вызываются шаги:
3. System class loader. Прежде всего делегирует вызов на загрузку класса своему родительскому classloader-у (номер 2). И только если родитель не смог загрузить класс, то пытается выполнить загрузку сам, из classpath. Список источников классов (jar-архивов и каталогов с *.class-файлами) указывается при запуске java-машины как параметр командной строки. Помните, что первый архив обладает приоритетом перед последующими. Т.е. System class loader просматривает эти архивы по очереди, в поисках определения нужного класса. Так что засорение classpath (указание в нем тысячи и одной библиотеки) несет массу проблем. Например, загрузка не той версии класса, что нужна для работы остальной части приложения.
1. Bootstrap class loader. Классы загружаются из rt.jar. Надо отметить, что sun-овцы создали механизм позволяющий внести изменения даже в процесс загрузки java-ядра. Т.е. bootstrap вовсе не является последней инстанцией в определении того откуда будут загружаться классы, и вы можете подменить реализацию даже такой фундаментальной вещи как java.lang.Object на свою собственную (ну наверное можно, я никогда такого не пробовал, хотя и интересно). Для этого при запуске jre вы указываете следующие параметры командной строки (взято из справки):
-Xbootclasspath:bootclasspath Specify a semicolon-separated list of directories, JAR archives, and ZIP archives to search for boot class files. These are used in place of the boot class files included in the Java 2 SDK. Note: Applications that use this option for the purpose of overriding a class in rt.jar should not be deployed as doing so would contravene the Java 2 Runtime Environment binary code license. -Xbootclasspath/a:path Specify a semicolon-separated path of directires, JAR archives, and ZIP archives to append to the default bootstrap class path. -Xbootclasspath/p:path Specify a semicolon-separated path of directires, JAR archives, and ZIP archives to prepend in front of the default bootstrap class path. Note: Applications that use this option for the purpose of overriding a class in rt.jar should not be deployed as doing so would contravene the Java 2 Runtime Environment binary code license.
При запуске виртуальной машины можно указать специальный параметр, включающий вывод на экран сведений об том какие классы и из каких источников загружаются.
java -verbose:class -classpath foo.jar;bar.jar my.Mega > log.txt (перенаправляю вывод сообщений с экрана в текстовый файл)
[Opened E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.Object from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.io.Serializable from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.Comparable from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.CharSequence from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.String from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.reflect.GenericDeclaration from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.reflect.Type from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.reflect.AnnotatedElement from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.Class from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.Cloneable from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.ClassLoader from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar] [Loaded java.lang.System from E:\Program_Files_2\j2dk1.6.0\jre\lib\rt.jar]
В верхней части окна размещены текстовые поля и кнопки выбора файлов журнала.
Указав имена файлов, вы жмете на кнопку "Compare" и после секундного ожидания видите что все закладки были заполнены информацией об загружаемых классах. На первой и второй закладках перечисляется список тех пар (класс и файл из которого он был загружен) которые соответствуют первому и второму файлу.
Информация представляется в двух формах: таблице и дереве. Как видите дерево устроено очень просто: список файлов образуют набор узлов первого уровня, в которые вложены узлы соответствующие загруженным классам. Для каждого файла-ресурса указывается статистика, сколько классов из файла было загружено.
Т.к. количество классов может быть (вернее всего будет) очень большим, то я добавил функцию фильтрации результатов по имени класса. Просто введите в текстовое поле выражение, содержащее часть имени класса (можно использовать символ * для задания шаблона). Нажав ввод вы примените фильтр (если поле пустое, то фильтр будет отменен).
Третья закладка "Common classes" похожа на первые две по функционалу, но представляет сведения об тех классах, которые были загружены из одних и тех же ресурсов в первом и втором случае.
Закладки "In 1 not 2" и "In 2 not 1", очевидно, хранят сведения об том какие классы были загружены в первом случае, но не загружены во втором и наоборот (совпадение проверяется по паре класс-файл).
Последняя закладка "Differect class storages" устроена отлично от ранее описанных: здесь только одна таблица с тремя колонками: "file 1", "clazz", "file 2". Т.е. так можно отследить ситуацию, когда один и тот же класс был загружен из двух различных ресурсов.
Исходники проекта размещены здесь: /java/compareloading
« Сложные интерфейсы на javascript вместе Yahoo UI. Часть 6 | Сложные интерфейсы на javascript вместе Yahoo UI. Часть 8 » |