JAVA 类加载原理 一时失言乱红尘 2023-02-17 15:52 1阅读 0赞 ### JAVA 类加载原理 ### * 类运行全过程 * * 前提知识点 * * 类加载器 * 什么是双亲委派机制 * 操作案例 * 总结 # 类运行全过程 # 在日常开发过程中,我们都会用到许许多多的类,跟我们开发息息相关,而了解他的加载原理那是重中之重; ## 前提知识点 ## 前提知识点很重要请仔细阅读,带着知识点跟着下方案例走。 首先大家请看这个段代码 public class Math { public static final int initData = 666; public static User user = new User(); public int compute() { //一个方法对应一块栈帧内存区域 int a = 1; int b = 2; int c = (a + b) * 10; return c; } public static void main(String[] args) { Math math = new Math(); math.compute(); } } 这是一段非常简单的代码,`new Maht`对象,调用`compute()`方法。 我们来简单的了解下它的加载流程 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70] 是不是很难理解,不着急,往下看 ### 类加载器 ### 我们先来看看几种**类加载器**: **1、引导类加载器(BootstarpLoader)**:由C++实现的加载器,负责加载支撑JVM运行位于JRE的lib目录下核心Java类,例如:rt.jar、charsets.jar等; **2、扩展类加载器(ExtClassLoader)**:负责加载支撑JVM运行位于JRE的ext扩展目录中的Jar类包; **3、应用程序加载器(AppClassLoader)**:负责加载ClassPath路径下的类包,说白话就是加载你自己写的类; **4、自定义类加载器**:负责加载用户自定义路径下的类包 `Math`对象加载流程可离不开上述几种加载器。 每种加载器都负责加载不同包路径下的类,有各自的分工,我们先来看看类加载器的核心类`Launcher` ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 1] `Launcher`中装载java类加载器`ExtClassLoader`与`AppClassLoader`,大致结构如下 public class Launcher { static class AppClassLoader extends URLClassLoader { } static class ExtClassLoader extends URLClassLoader { } } 可以看出这两个类加载器存放在Launcher中的两个内部类,他们公共继承了 `URLClassLoader`,`URLClassLoader` 最终继承了`ClassLoader` ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 2] 而`BootstarpLoader`,他是由C++所实现的类,由C++发起调用,我们在jdk源码中是看不到的,感兴趣的可以去看看HotSpot源码。 我们大致了解加载器的基本结构后,再来看看**双亲委派机制** ### 什么是双亲委派机制 ### ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 3] 双亲委派机制是指,**加载某个类时会先委托父加载器寻找目标类,找不到再委托上层父加载器加载,如果所有父加载器在自己的加载类路径下都找不到目标类,则在委托子类加载器寻找,直至找到该类**; 而JDK类加载中就使用了双亲委派机制,比如我们的`Math`类,最先会找应用程序类加载器加载(**AppClassLoader**),应用程序类加载器会先委托扩展类加载器(**ExtClassLoader**)加载,扩展类加载器再委托引导类加载器(**BootstarpLoader**),顶层引导类加载器在自己的类加载路径里找了半天没找到Math类,则向下退回加载Math类的请求,扩展类加载器收到回复就自己加载,在自己的类加载路径里找了半天也没找到Math类,又向下退回Math类的加载请求给应用程序类加载器,应用程序类加载器于是在自己的类加载路径里找Math类,结果找到了就自己加载了。。 我们来看看下面这个案例: public class TestJDKClassLoader { public static void main(String[] args) { //获取String类的加载器 System.out.println(String.class.getClassLoader()); //获取扩展类加载器 System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName()); //获取Target目录下类加载器,也就是自己写的类 System.out.println(TestJDKClassLoader.class.getClassLoader().getClass().getName()); System.out.println(); //获取各个加载器的父加载器 ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); ClassLoader extClassloader = appClassLoader.getParent(); ClassLoader bootstrapLoader = extClassloader.getParent(); System.out.println("the bootstrapLoader : " + bootstrapLoader); System.out.println("the extClassloader : " + extClassloader); System.out.println("the appClassLoader : " + appClassLoader); System.out.println(); System.out.println("bootstrapLoader加载以下文件:"); URL[] urls = Launcher.getBootstrapClassPath().getURLs(); for (int i = 0; i < urls.length; i++) { System.out.println(urls[i]); } System.out.println(); System.out.println("extClassloader加载以下文件:"); System.out.println(System.getProperty("java.ext.dirs")); System.out.println(); // appClassLoader 他会打印所有的 加载类路径 但是 会去读取不会去加载 System.out.println("appClassLoader加载以下文件:"); System.out.println(System.getProperty("java.class.path")); } } // ------------------------输出内容如下---------------------------- //BootstrapLoader 是C++实现 所以输出为null null sun.misc.Launcher$ExtClassLoader sun.misc.Launcher$AppClassLoader the bootstrapLoader : null the extClassloader : sun.misc.Launcher$ExtClassLoader@3764951d the appClassLoader : sun.misc.Launcher$AppClassLoader@14dad5dc bootstrapLoader加载以下文件: file:/D:/dev/Java/jdk1.8.0_45/jre/lib/resources.jar file:/D:/dev/Java/jdk1.8.0_45/jre/lib/rt.jar file:/D:/dev/Java/jdk1.8.0_45/jre/lib/sunrsasign.jar file:/D:/dev/Java/jdk1.8.0_45/jre/lib/jsse.jar file:/D:/dev/Java/jdk1.8.0_45/jre/lib/jce.jar file:/D:/dev/Java/jdk1.8.0_45/jre/lib/charsets.jar file:/D:/dev/Java/jdk1.8.0_45/jre/lib/jfr.jar file:/D:/dev/Java/jdk1.8.0_45/jre/classes extClassloader加载以下文件: D:\dev\Java\jdk1.8.0_45\jre\lib\ext;C:\Windows\Sun\Java\lib\ext appClassLoader加载以下文件: D:\dev\Java\jdk1.8.0_45\jre\lib\charsets.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\deploy.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\access-bridge-64.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\cldrdata.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\dnsns.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\jaccess.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\jfxrt.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\localedata.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\nashorn.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\sunec.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\sunjce_provider.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\sunmscapi.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\sunpkcs11.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\ext\zipfs.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\javaws.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\jce.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\jfr.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\jfxswt.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\jsse.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\management-agent.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\plugin.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\resources.jar;D:\dev\Java\jdk1.8.0_45\jre\lib\rt.jar;D:\ideaProjects\project-all\target\classes;C:\Users\zhuge\.m2\repository\org\apache\zookeeper\zookeeper\3.4.12\zookeeper-3.4.12.jar;C:\Users\zhuge\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\zhuge\.m2\repository\org\slf4j\slf4j-log4j12\1.7.25\slf4j-log4j12-1.7.25.jar;C:\Users\zhuge\.m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;C:\Users\zhuge\.m2\repository\jline\jline\0.9.94\jline-0.9.94.jar;C:\Users\zhuge\.m2\repository\org\apache\yetus\audience-annotations\0.5.0\audience-annotations-0.5.0.jar;C:\Users\zhuge\.m2\repository\io\netty\netty\3.10.6.Final\netty-3.10.6.Final.jar;C:\Users\zhuge\.m2\repository\com\google\guava\guava\22.0\guava-22.0.jar;C:\Users\zhuge\.m2\repository\com\google\code\findbugs\jsr305\1.3.9\jsr305-1.3.9.jar;C:\Users\zhuge\.m2\repository\com\google\errorprone\error_prone_annotations\2.0.18\error_prone_annotations-2.0.18.jar;C:\Users\zhuge\.m2\repository\com\google\j2objc\j2objc-annotations\1.1\j2objc-annotations-1.1.jar;C:\Users\zhuge\.m2\repository\org\codehaus\mojo\animal-sniffer-annotations\1.14\animal-sniffer-annotations-1.14.jar;D:\dev\IntelliJ IDEA 2018.3.2\lib\idea_rt.jar 现在大致了解什么是类加载器与双亲委派机制 后我们来进入实战。 ## 操作案例 ## **接下来进入源码** 为了方便快速理解,从核心方法,由核心类慢慢扩展理解 请看`Launcher` 核心类中的`loadClass()`方法 public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException { int var3 = var1.lastIndexOf(46); if (var3 != -1) { SecurityManager var4 = System.getSecurityManager(); if (var4 != null) { var4.checkPackageAccess(var1.substring(0, var3)); } } if (this.ucp.knownToNotExist(var1)) { Class var5 = this.findLoadedClass(var1); if (var5 != null) { if (var2) { this.resolveClass(var5); } return var5; } else { throw new ClassNotFoundException(var1); } } else { return super.loadClass(var1, var2); } } 首先这个方法有两个参数`String var1, boolean var2` ,var2这个参数不做考虑,而var1他是我们加载类的包名路径; 我们用Debug打个断点看看,右击给断点设置条件`var1.equals("com.example.demo03.demo.Math")` ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 4] 我们已经把`Math`类拦截下来了, 前面有多个if语句,都是类加载的初始化过程,他最后调用了父类(ClassLoader)`super.loadClass(var1, var2)`方法,我们直接跳进去。 父类ClassLoader: 这个方法**非常重要**了,此方法实现了双亲委派机制。 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { //如果父加载器不为空 使用父加载器(此处实现了双亲委派机制) c = parent.loadClass(name, false); } else { //findBootstrapClassOrNull 为native方法,根据name加载类 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } //如果c为null,即加载失败 if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); //委派自己子类找,最终他会调用URlClassLoader类的findClass方法 c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } } 我们可以看到核心逻辑代码都被`synchronized`包裹着,加上了`getClassLoadingLock(name)`锁,所以他是线程安全的; ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 5] 我们再往下看,调用`findLoadedClass(name)`方法找到此加载类,如果`c=null`也就是Math没有加载,那他必定会进入if语句 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 6] 进入if语句后,可以看到`try/catch`代码块 try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } 如果`parent`不为空,则使用`parent`调用加载类方法; `parent` 是什么,怎么来的? `parent` 其实就是`ClassLoader`中的一个参数,里面装着类加载器它的父加载器 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 7] 看看他是如何赋值的,看下`Launcher.class`类的构造方法 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 8] 调用了两个类加载器的初始化方法,点进去看看 `ExtClassLoader`: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 9] 再次进去,**注意(classLoader)为null** ![在这里插入图片描述][20200626114915431.png] 可以看到他调用父类的方法,点到最后,会进入最终父类`ClassLoader`方法 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 10] 我们可以知道ExtClassLoader 他的parent是null,按照双亲委派他应该为`bootstarpLoader`,因为他是由C++实现所以他为null,而`AppClassLoder`亦是如此,只不过他的parent放入的是ExtClassLoader ![在这里插入图片描述][20200626120405405.png] 上述方法都是由C++来调用的所以debug断点是拦截不到的 回到`loadClass`方法 首先,调用了`findLoadedClass(name)`方法,查找该类是否已被加载吗,如果为空,则使用自己父加载器`parent.loadClass(name, false)`再次调用此方法,如果`parent`为空,则调用`findBootstrapClassOrNull(name)`方法加载类。 如果未找到,则会调用`findClass(name)`,委派子加载器加载,最终他会调用`URLClassLoader findClass(final String name)` URLClassLoader: protected Class<?> findClass(final String name) throws ClassNotFoundException { final Class<?> result; try { result = AccessController.doPrivileged( new PrivilegedExceptionAction<Class<?>>() { //拼接类名全路径 public Class<?> run() throws ClassNotFoundException { String path = name.replace('.', '/').concat(".class"); Resource res = ucp.getResource(path, false); if (res != null) { try { //记载类 return defineClass(name, res); } catch (IOException e) { throw new ClassNotFoundException(name, e); } } else { return null; } } }, acc); } catch (java.security.PrivilegedActionException pae) { throw (ClassNotFoundException) pae.getException(); } if (result == null) { throw new ClassNotFoundException(name); } return result; } 会调用 `defineClass`方法,而此方法是本地方法无法看到,了解大致流程就可以了 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 11] # 总结 # 1、初始化ExtClassLoader 与 AppClassLoder 给 parent 赋值(实现双亲委派前提); 2、调用核心方法loadclass,使用parent调用自己递归,从而实现双亲委派; 3、最终向下委派,调用findClass加载类; [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70]: https://img-blog.csdnimg.cn/20200616002412282.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 1]: https://img-blog.csdnimg.cn/20200614225035542.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 2]: https://img-blog.csdnimg.cn/20200616004213994.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 3]: https://img-blog.csdnimg.cn/20200618224301406.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 4]: https://img-blog.csdnimg.cn/2020062123432586.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 5]: https://img-blog.csdnimg.cn/20200621235037764.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 6]: https://img-blog.csdnimg.cn/20200621235440319.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 7]: https://img-blog.csdnimg.cn/20200626135508617.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 8]: https://img-blog.csdnimg.cn/20200626114744212.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 9]: https://img-blog.csdnimg.cn/20200626114858280.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [20200626114915431.png]: https://img-blog.csdnimg.cn/20200626114915431.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 10]: https://img-blog.csdnimg.cn/20200626115230484.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70 [20200626120405405.png]: https://img-blog.csdnimg.cn/20200626120405405.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4_size_16_color_FFFFFF_t_70 11]: https://img-blog.csdnimg.cn/20200626122221979.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNDY5NzE4,size_16,color_FFFFFF,t_70
相关 Java类加载器的工作原理 Java类加载器是Java虚拟机(JVM)中的一个重要组件,负责管理和加载Java类。其工作原理主要分为以下几步: 1. **资源搜索**:当Java程序需要使用某个类时,会 港控/mmm°/ 2024年10月24日 20:03/ 0 赞/ 30 阅读
相关 类加载器原理:Java中类加载器如何实现对Java类的管理和加载? 在Java中,类加载器(Class Loader)是负责将字节码文件转化为Java类,并在其上下文中实例化这些类的关键角色。 具体实现如下: 1. **Bootstrap ﹏ヽ暗。殇╰゛Y/ 2024年10月22日 22:18/ 0 赞/ 33 阅读
相关 Java类加载器原理:类加载失败常见问题及解决 Java类加载器是Java应用环境中负责加载类的重要组件。它的工作原理主要包括以下几个步骤: 1. 首先,类加载请求到达,通常是通过Java虚拟机(JVM)中的类加载API。 柔情只为你懂/ 2024年09月21日 04:39/ 0 赞/ 85 阅读
相关 类加载器原理:Java中类加载问题及解决办法 在Java中,类加载是一个复杂的过程,主要包括以下步骤: 1. 类的加载:当程序运行到需要使用某个类时(如创建对象),如果该类还没有被任何类加载器加载过,那么就由最合适的类加 Love The Way You Lie/ 2024年09月11日 00:03/ 0 赞/ 73 阅读
相关 java类加载过程(java类加载过程) Java加载类的机制是怎样的? sun。com/developer /TechTips/2000/tt1027。html Writing Your Own Class ゝ一世哀愁。/ 2023年09月26日 15:30/ 0 赞/ 217 阅读
相关 Java的类加载机制原理 首先简要的说一下类加载器 我们知道,虚拟机的指令存储在以.class为扩展名的类文件中。那么虚拟机如何调用这些.class文件呢。先看一下虚拟机执行的步骤: 1. 红太狼/ 2022年07月14日 10:52/ 0 赞/ 164 阅读
相关 理解Java类加载原理 本文转自:[http://www.moon-soft.com/doc/22670.htm][http_www.moon-soft.com_doc_22670.htm] 第一部 阳光穿透心脏的1/2处/ 2022年05月15日 06:15/ 0 赞/ 118 阅读
相关 类加载原理 第一部分. 提示 我需要读这篇文章吗? Java类加载器对Java系统的运行是至关重要的,但是却常常被我们忽略。Java类加载器负载 在运行时查找和加载类。自定义类 Bertha 。/ 2022年04月17日 01:27/ 0 赞/ 124 阅读
还没有评论,来说两句吧...