Механизм загрузки классов Java для ссылочных классов - PullRequest
0 голосов
/ 03 апреля 2019

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

class A extends B implements C,D {

    static E e;

    F f;

    A() {

      G g = new G();

    }

    void print(H h) {

    }
}

Загружает ли JVM все классы, которые используются A? Или это не беспокоит их, пока класс не инициализирован?

Если хотя бы некоторые из них загружены, будут ли они загружены после завершения A? или A's загрузка будет приостановлена ​​до загрузки требуемого класса?

Для этого вопроса предположим, что ни один из других классов еще не загружен. Даже супер класс B и интерфейсы C & D.

1 Ответ

1 голос
/ 03 апреля 2019

Чтобы понять это, позвольте понять некоторые основы для этого.Это поможет любому новичку понять ленивую загрузку в JAVA.

Если вы знакомы с веб-браузером Netscape и использовали обе версии 3.x и 4.x, несомненно, вы заметили разницу в том, каксреда выполнения Java загружена.Если вы посмотрите на заставку при запуске Netscape 3, вы заметите, что он загружает различные ресурсы, включая Java.Однако когда вы запускаете Netscape 4.x, он не загружает среду выполнения Java - он ждет, пока вы не посетите веб-страницу, содержащую тег.Эти два подхода иллюстрируют методы быстрого создания экземпляров (загружайте его в случае необходимости) и отложенного создания экземпляров (дождитесь его запроса, прежде чем загружать его, так как он может никогда не понадобиться).

У обоих подходов есть недостатки: С одной стороны, постоянная загрузка ресурса может привести к бесполезной трате драгоценной памяти, если ресурс не используется во время этого сеанса;с другой стороны, если он не был загружен, вы платите цену с точки зрения времени загрузки, когда ресурс впервые требуется.

Рассматривайте ленивую реализацию как политику сохранения ресурса

Ленивые экземпляры в Java делятся на две категории:

  • Ленивая загрузка классов
  • Элемент списка

Ленивая загрузка классов

Среда выполнения Java имеет встроенную отложенную реализацию для классов.Классы загружаются в память только при первом обращении к ним.(Они также могут быть сначала загружены с веб-сервера через HTTP.)

 MyUtils.classMethod();   //first call to a static class method
 Vector v = new Vector(); //first call to operator new

Ленивая загрузка классов является важной особенностью среды выполнения Java, поскольку она может уменьшить использование памяти при определенных обстоятельствах.Например, если часть программы никогда не выполняется во время сеанса, классы, на которые есть ссылки только в этой части программы, никогда не будут загружены.

Создание отложенного объекта

Создание ленивых объектов тесно связано с загрузкой ленивых классов.При первом использовании нового ключевого слова в типе класса, который ранее не загружался, среда выполнения Java загрузит его для вас.Создание отложенных объектов может уменьшить использование памяти в гораздо большей степени, чем загрузка отложенных классов.

Чтобы представить концепцию создания отложенных объектов, давайте рассмотрим простой пример кода, где Frame использует MessageBox для отображения ошибки.messages:

   public class MyFrame extends Frame
  {
  private MessageBox mb_ = new MessageBox();
  //private helper used by this class
  private void showMessage(String message)
  {
    //set the message text
    mb_.setMessage( message );
    mb_.pack();
    mb_.show();
  }
}

В приведенном выше примере, когда создается экземпляр MyFrame, также создается экземпляр MessageBox mb_.Те же правила применяются рекурсивно.Таким образом, любые переменные экземпляра, инициализированные или назначенные в конструкторе класса MessageBox, также выделяются из кучи и так далее.Если экземпляр MyFrame не используется для отображения сообщения об ошибке в сеансе, мы напрасно тратим память.

В этом довольно простом примере мы не собираемся слишком много выигрывать.Но если вы рассмотрите более сложный класс, который использует много других классов, которые, в свою очередь, используют и создают больше объектов рекурсивно, потенциальное использование памяти становится более очевидным.

  public final class MyFrame extends Frame
  {
  private MessageBox mb_ ; //null, implicit
  //private helper used by this class
  private void showMessage(String message)
  {
    if(mb_==null)//first call to this method
      mb_=new MessageBox();
    //set the message text
    mb_.setMessage( message );
    mb_.pack();
    mb_.show();
  }
}

Если вы присмотритесь к showMessage поближе(), вы увидите, что сначала мы определяем, равна ли переменная экземпляра mb_ нулю.Поскольку мы не инициализировали mb_ в точке его объявления, среда выполнения Java позаботилась об этом за нас.Таким образом, мы можем безопасно продолжить работу, создав экземпляр MessageBox.Все последующие вызовы showMessage () обнаружат, что mb_ не равно нулю, поэтому пропускает создание объекта и использует существующий экземпляр.

Заключение : он загрузит все зависимые объектыкак только они инициализируются дочерними объектами. Чтобы уменьшить объем памяти, мы должны внимательно искать такие шаблоны проектирования, такие как Виртуальный прокси, Ленивая инициализация

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