Java ClassLoader и разрешение зависимостей - PullRequest
5 голосов
/ 17 декабря 2010

Может кто-нибудь уточнить, что роль ClassLoader заключается не только в загрузке отдельного класса, но и его зависимостей?И если так, что именно влечет за собой весь процесс?Я ищу детали реализации, если это вообще возможно.

Например, в какой-то момент байты должны будут быть откуда-то считаны (расположение в сети или файловой системе), а расположения файловой системырассчитываться на основе канонического имени класса и предузнания путей к классам, доступных для JVM. Как отдельный ClassLoader пытается найти файл по потенциально нескольким путям классов?Откуда он получает эту информацию?Кроме того, в какой момент проверяются байты файлов класса и проверяются его зависимости на доступность?

Было бы желательно узнать как можно больше подробностей:)

Ответы [ 2 ]

7 голосов
/ 17 декабря 2010

ClassLoading - очень сложный предмет. Модель безопасности ClassLoader и Java неразрывно связаны друг с другом. По сути, JVM загружает классы по требованию. При наличии иерархии загрузчиков классов JVM пытается разрешить класс как можно дальше вниз по цепочке. Короче говоря, если класс определен в загрузчике классов «boot» и в загрузчике классов, определенных приложением, он всегда будет использовать версию в загрузчике классов загрузки.

В загрузчике классов, таком как URLClassLoader, порядок поиска - это порядок, в котором вы сказали ему искать. По сути, массив URL-адресов, которые, как вы сказали, содержат классы, будет найден от первой записи до последней.

Когда определенный вами класс ссылается на другой класс, этот класс также разрешается с использованием того же алгоритма. Но здесь есть одна загвоздка: она только разрешает ее относительно того, где она была найдена. Давайте рассмотрим сценарий, в котором класс SomeCoolThing находится в загрузчике загрузчика классов, но зависит от SomeLameThing, который находится в определяемом приложением загрузчике классов. Процесс будет выглядеть так:

App-ClassLoader: resolveClass("SomeCoolThing")
    parent->resolveClass("SomeCoolThing")

Boot-ClassLoader (the ultimate parent): resolveClass("SomeCoolThing")
    SomeCoolThing needs SomeLameThing
    resolveClass("SomeLameThing") // Can't find SomeLameThing!!!!

Несмотря на то, что SomeLameThing находится в загрузчике классов, где вы запросили SomeCoolThing, SomeCoolThing был разрешен в другом загрузчике классов. Этот другой загрузчик классов не знает дочерний загрузчик классов, и пытается разрешить его сам и завершается неудачей.

У меня была книга давным-давно, которая очень подробно рассказывала о Java ClassLoaders, и я рекомендую ее. Это Безопасность Java от O'Reilly Media . Он ответит на все вопросы, которые вы никогда не хотели знать, но все же должны знать, когда имеете дело с ClassLoaders и как они работают.

0 голосов
/ 17 декабря 2010

Я могу ответить на некоторые ваши вопросы:

как отдельный ClassLoader пытается найти файл по потенциально нескольким путям классов?

Если вы имеете в виду разныеЗагрузчики классов имеют разные пути к классам, тогда каждый загрузчик классов принимает свойства (то есть путь к классам) родительского загрузчика классов.При прочих равных у каждого загрузчика классов тот же путь к классам, что и у любого другого (я верю; не уверен, что JVM делает что-то странное внутри).Таким образом, MyClass.class одинаков для загрузчика классов и всех дочерних загрузчиков классов.Если у вас есть несколько MyClass.class, определенных в одном и том же пути к классам, JVM подхватывает первый.В прошлом я создавал свой собственный загрузчик классов и добавлял собственный путь к классу к существующему пути к классам, чтобы загружать классы во время выполнения, которых при запуске не было в пути к классам.Я уверен, что есть спецификация, которая описывает это, или вы можете скачать код JVM (код ассемблера / C / C ++) и сделать это, но я должен был это сделать, и "это не красиво".

Конечно, "они" меняют классовую дорожку в 1.7, поэтому я не уверен, как это сработает ...

Надеюсь, это немного поможет ...

...