- Русские Блоги
- Механизм работы ClassLoader и анализ нескольких ошибок загрузки
- 1. Рабочий механизм ClassLoader
- 2. Механизм загрузки уровня
- 3. Анализ типичных ошибок загрузки.
- 1. Уточнение концепции:
- 2、ClassNotFoundException
- 3、NoClassDefFoundError
- 4、UnsatisfiedLinkError
- 5、 ClassCastException
- 6、ExceptionInInitializerError
Русские Блоги
Механизм работы ClassLoader и анализ нескольких ошибок загрузки
1. Рабочий механизм ClassLoader
Отвечает за загрузку класса в JVM, проверку того, кто загружает каждый класс (механизм иерархической загрузки «родительский приоритет»), и повторную интерпретацию байт-кода класса в формат объекта, требуемый JVM.
- defineClass (byte [], int, int) — разбирает байтовый поток на объекты, которые могут быть распознаны JVM
- findClass (String) — реализовать правила загрузки класса и получить байт-код, необходимый для указанной выше функции
- loadClass (String) — Получить объект Class этого класса
- resolveClass (Class ) — ссылка на класс (ссылка)
2. Механизм загрузки уровня
Примечание: начальник доверяет механизм приема, сначала проверяет, был ли он загружен сам по себе, затем спрашивает начальника, начальник также проверяет, загружен ли он, а затем спрашивает начальника, нужно ли его загружать старшим, если нет, проверьте сами Правила загрузки, чтобы определить, загружать ли самостоятельно.
BootStrapClassLoader — класс, необходимый самой JVM для работы, сама служба, без родительского / дочернего загрузчика
ExtClassLoader — конкретная цель службы, System.getProperty («java.ext.dirs»)
AppClassLoader — родительский класс ExtClassLoader, System.getProperty («java.class.path»)
Углубленное понимание механизма загрузки классов виртуальной машины Java и JVM (процесс загрузки классов и загрузчик классов):
3. Анализ типичных ошибок загрузки.
1. Уточнение концепции:
JVM может загружать файлы классов в память двумя способами.
◎ Неявная загрузка: так называемая неявная загрузка — это способ загрузки требуемых классов не путем вызова ClassLoader в коде, а для автоматической загрузки требуемых классов в память через JVM. Например, когда мы наследуем или ссылаемся на определенный класс в классе, JVM обнаруживает, что указанный класс не находится в памяти при анализе текущего класса, а затем автоматически загружает эти классы в память.
◎ Явная загрузка: противоположностью явной загрузки является способ загрузки класса путем вызова класса ClassLoader в коде, например, вызывая this.getClass.getClassLoader (). loadClass () Или метод Class. ForName (), или метод findClass () класса ClassLoader, реализованный нами самими.
Фактически, эти два метода смешаны. Например, когда мы загружаем класс через пользовательский дисплей ClassLoader, этот класс ссылается на другие классы, тогда эти классы загружаются неявно.
2、ClassNotFoundException
Это исключение обычно возникает, когда класс загружается явным образом. Например, об этой ошибке сообщается, когда класс загружается следующим образом:
public class notfountexception < public static void main(String[] args) < try < Class.forName("notFountClass"); >catch (ClassNotFoundException e) < e.printStackTrace(); >> >
Обычно есть следующие способы явно загрузить класс:
◎ С помощью метода forName () в классе Class.
◎ С помощью метода loadClass () в ClassLoader.
◎ С помощью метода findSystemClass () в ClassLoader.
Этот вид ошибки также легко понять, то есть, когда JVM хочет загрузить байт-код указанного файла в память, она не находит байт-код, соответствующий этому файлу, то есть этот файл не существует. Решение состоит в том, чтобы проверить, существует ли указанный файл в текущем каталоге пути к классам. Если вы не знаете текущий путь к классам, вы можете получить его с помощью следующей команды:
this.getClass().getClassLoader().getResource(«»).toString()
3、NoClassDefFoundError
NoClassDefFoundError — еще одно часто встречающееся исключение. Это исключение может возникнуть при первом выполнении класса Java с использованием командной строки, например в следующей ситуации:
java –cp example.jar Example
В этом пакете jar есть только один класс. Это класс net.xulingbo.Example. Что может вас расстроить, так это то, что если в этом пакете jar есть этот класс, следующая ошибка Будет сообщено Что?
Exception in thread "main" java.lang.NoClassDefFoundError: example/jar Caused by: java.lang.ClassNotFoundException: example.jar at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
Это связано с тем, что вы не добавили имя пакета класса в командную строку. Правильный способ записи следующий:
java –cp example.jar net.xulingbo.Example
Здесь сообщаются как NoClassDefFoundError, так и ClassNotFoundException. Причина в том, что виртуальная машина Java неявно загружает example.jar, а затем явно загружает класс Example, который не найден, поэтому ClassNotFoundException вызывает NoClassDefFoundError исключение.
Спецификация JVM описывает возможную ситуацию NoClassDefFoundError, заключающуюся в использовании нового ключевого слова, атрибута для ссылки на определенный класс, наследования определенного интерфейса или класса и ссылки на определенный параметр метода. Для определенного класса он заставит JVM неявно загрузить эти классы и обнаружить, что эти классы не существуют.
Решение этой ошибки — убедиться, что классы, на которые ссылается каждый класс, находятся в текущем пути к классам.
4、UnsatisfiedLinkError
Это исключение не очень распространено, но если возникает ошибка, обычно это происходит при запуске JVM. Если определенная библиотека в JVM случайно удалена, об этой ошибке может быть сообщено., следующее:
public class NoLibException < public native void nativeMethod(); static < System.loadLibrary("NoLib"); >public static void main(String[] args) < new NoLibException().nativeMethod(); >>
Эта ошибка обычно возникает, когда JVM не может найти соответствующий файл собственной библиотеки при анализе собственного метода идентификации. ,следующее:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no NoLib in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864) at java.lang.Runtime.loadLibrary0(Runtime.java:840) at java.lang.System.loadLibrary(System.java:1084) at EmptyProject.classloader.NoLibException.(NoLibException. java:12) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:107)
5、 ClassCastException
Эта ошибка также очень распространена, обычно когда в программе происходит принудительное преобразование типа, как показано в следующем коде:
public class CastException < public static Map m = new HashMap()>; public static void main(String[] args) < Integer isInt = (Integer)m.get("a"); System.out.print(isInt); >>
При принудительном преобразовании строки, не являющейся целочисленным типом, в целочисленный тип, будет выдана следующая ошибка:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at EmptyProject.classloader.CastException.main(CastException.java:17) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessor- Impl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethod- AccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:613) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:110)
JVM будет проверять в соответствии со следующими правилами при преобразовании типов:
◎ Для обычных объектов объект должен быть экземпляром целевого класса или экземпляром подкласса целевого класса. Если целевой класс является интерфейсом, он будет рассматриваться как подкласс, реализующий интерфейс.
◎ Для типов массивов целевой класс должен быть типом массива или java.lang.Object, java.lang. Cloneable, java.io.Serializable.
Если указанные выше правила не соблюдаются, JVM сообщит об этой ошибке. Есть два способа избежать этой ошибки:
◎ В типе контейнера явно укажите тип объекта, содержащегося в контейнере. Например, на приведенной выше карте это можно записать как Map m = new HashMap. (), так что приведенный выше код будет проверен на этапе компиляции.
◎ Сначала проверьте, является ли это целевым типом, с помощью instanceof, а затем выполните принудительное преобразование типа.
6、ExceptionInInitializerError
Эта ошибка определена в спецификации JVM:
◎ Если виртуальная машина Java пытается создать новый экземпляр класса ExceptionInInitializerError, но не может создать новый экземпляр из-за ошибки Out-Of-Memory, то создается объект OutOfMemoryError. вместо.
◎ Если инициализатор выдает какое-то исключение, а класс Exception не является Error или одним из его подклассов, то будет создан новый экземпляр класса ExceptionInInitializerError, и Exception будет использоваться как Параметр Используйте этот экземпляр вместо исключения.
Немного измените приведенный выше пример кода:
public class CastException < public static Map m = new HashMap()>; public static void main(String[] args) < Integer isInt = (Integer)m.get("a"); System.out.print(isInt); >>
При выполнении этого кода будет выдана следующая ошибка:
Exception in thread "main" java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:107) Caused by: java.lang.NullPointerException at EmptyProject.classloader.CastException$1.(CastException. java:14) at EmptyProject.classloader.CastException.(CastException. java:13) . 3 more
При инициализации этого класса возникло исключение при присвоении значения статическому свойству m, что привело к возникновению исключения ExceptionInInitializerError.
«Углубленный анализ инсайдеров веб-технологий Java»