Как и когда загружается файл Bootstrap jar ../ lib / rt.jar и ../lib/ext.**jar? - PullRequest
2 голосов
/ 14 марта 2012

У меня есть два класса, перечисленных ниже

package foo;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

public class CustomClassLoader extends ClassLoader {
    public CustomClassLoader(ClassLoader parent){
        super(parent);
    }

    public Class<?> loadClass(String name) throws ClassNotFoundException {
        System.out.println( " >>> loading " + name );

        if (name.startsWith("foo")) {
            return getClass(name);
        }
        return super.loadClass(name);
    }

    public Class getClass(String name){
        try {
            byte[] data= getClassByteData(name);
            return this.defineClass(name, data, 0, data.length);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public byte[] getClassByteData(String name) throws IOException {
        String file = name.replace(".", File.separator)+".class";
        InputStream in   = this.getClass().getResourceAsStream("/"+file);
        int length = in.available();
        byte[] datas = new byte[length];
        in.read(datas, 0, length);
        return datas;
    }
}


package foo;

public class Test {
    public static void main(String[] args) {
        System.out.println(" Who is my loader? >>" + Test.class.getClassLoader());
    }

}

Выполнение: java -Djava.system.class.loader=foo.CustomClassLoader foo.Test

Вывод:

 >>> loading java.lang.System
 >>> loading java.nio.charset.Charset
 >>> loading java.lang.String
 >>> loading foo.Test
 >>> loading java.lang.Object
 >>> loading java.lang.StringBuilder
 >>> loading java.lang.Class
 >>> loading java.io.PrintStream
 Who is my loader? >>foo.CustomClassLoader@de6ced

Мои вопросы приведены ниже:

  1. Почему эти java.lang.System, java.nio.charset.Charset и т. Д., Как указано выше, будут загружены CustomClassLoader?В моих идеях я думаю, что когда я запускаю java -Djava.system.class.loader foo.Test, JVM сначала ищет класс foo.Test, загружает его, выполняет основной метод, а затем, когда он обнаруживает System.out.println(), он продолжает загружать класс java.lang.System и * 1021.* потому что эти классы используются им, верно?

  2. Когда я запускаю класс, который использует некоторые классы, расположенные в пакете java.lang, эти классы также будут загружены снова, в моем случаеделегированный CustomClassLoader >> ExtClassLoader >> BoostrapClassLoader для загрузки?

  3. Когда загружены /lib/rt.jar и /lib/ext/**.jar, прежде чем мы запустим такой класс, как java foo.Test, все эти классы уже загружены.?

Спасибо всем за помощь заранее!

Ответы [ 2 ]

3 голосов
/ 14 марта 2012

Чтобы ответить на ваши вопросы, давайте рассмотрим их по очереди.

  1. Механизм Java ClassLoading основан на модели делегирования, где попытка загрузки класса обычно сначала делегируется родительским загрузчикам классов.,Если загрузчик родительского класса может успешно загрузить класс, то загруженный класс передается обратно вниз по цепочке делегатов и возвращается тем загрузчиком класса, который был первоначально вызван.Поскольку вы установили свой загрузчик классов как загрузчик системных классов, JVM создала его как загрузчик по умолчанию, используемый при запуске приложения.Затем он используется для загрузки всех классов, которые ему нужны.Большинство этих классов (то есть все, что не начинается с foo. *) Делегируются родительским загрузчикам классов, что объясняет, почему вы видите сообщения о том, что ваш загрузчик классов пытается их загрузить.

  2. Поскольку загрузка классов, отличных от foo. *, Делегирована загрузчику родительского класса, загрузка системного класса, такого как System.out, снова будет обрабатываться загрузчиком родительского класса, который обрабатывает кэширование всех загруженных классов и возвращаетранее загруженный экземпляр.

  3. Загрузка файлов rt.jar и lib / ext / *. jar обрабатывается загрузчиком родительского класса (или его родителем), а не вами.Следовательно, загрузчику классов не нужно заниматься этими файлами JAR.

Как правило, пользовательский загрузчик классов создается для обеспечения возможности загрузки классов из нестандартных файлов.местоположение, например JAR-файлы, хранящиеся в базе данных.

2 голосов
/ 14 марта 2012

Я предполагаю, что текущая командная строка, которую вы используете, - java -Djava.system.class.loader=foo.CustomClassLoader foo.Test.

  1. Как правило, все классы могут загружаться несколько раз разными загрузчиками классов. На самом деле они даже считаются разными классами. Итак, для foo.Test нужна java.lang.System, для ее загрузки или загрузки вызывается загрузчик классов.

  2. В вашем случае CustomClassLoader делегирует загрузку класса не foo супер, который не загружает тот же класс во второй раз, но возвращает ранее загруженный.

  3. Говоря о загрузке банок в заблуждение. Классы из этих банок загружаются индивидуально по запросу. Для загрузки любой программы JVM необходимо создать поток, поэтому класс Thread и его зависимости загружаются еще до вашего класса.

вы можете запустить Sun Java с -verbose: class, чтобы увидеть, как загружаются классы.

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