JVM学习(2):类加载器
2020-03-12 16:04:25来源:博客园 阅读 ()
JVM学习(2):类加载器
什么是类加载器:
public class ClassInit { public static void main(String[] args) { ClassLoader c=ClassInit.class.getClassLoader(); } }
上面这个ClassLoader就是类加载器
打印c,注意到一个Launcher类:
sun.misc.Launcher$AppClassLoader@18b4aac2
进入Launcher类,注意到其中的两段代码:
var1 = Launcher.ExtClassLoader.getExtClassLoader(); this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
其中的ExtClassLoader和AppClassLoader有什么关系呢?
修改成如下代码:
public class ClassInit { public static void main(String[] args) { ClassLoader c = ClassInit.class.getClassLoader(); while (c != null) { System.out.println(c); c = c.getParent(); } } }
打印:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1540e19d
于是得到了结论:AppClassLoader有一个父亲是ExtClassLoader
继续分析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 { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e)
独占锁保证了同时只能加载一个类
然后检查这个类是否被加载过,如果被加载过直接返回;
如果没有被加载过,那么就递归加载他的父亲,直到没有父亲,最后执行findBootstrapClassOrNull()
往下看发现这样一段代码:
// return null if not found private native Class<?> findBootstrapClass(String name);
这个函数没有函数体,被native修饰,代表调用一个本地方法
这里调用本地方法,根据操作系统的不同,调用的本地方法接口不同,然后调用本地方法库
得出结论:
一个类的加载顺序是:BootstrapClassLoader--->ExtClassLoader--->AppClassLoader
一个类的检查顺序是:AppClassLoader--->ExtClassLoader--->BootstrapClassLoader
为什么加载顺序要从BootstrapClassLoader开始呢?
写一个新代码,包名和类名与java源码的List一样:
package java.util; public class List{ public static void main(String[] args){ xxxxxx } }
发现无法运行,报错:在类java.util.List中找不到main方法
无法运行是非常合理的,否则一个黑客岂不是可以轻易植入病毒代码,然后通过自定义类加载器加入到JVM中
这种机制称为:双亲委任
目的:安全
1.父类如果可以加载,那么不允许子类加载
2.保证一个类只加载一次
判断两个对象是不是相等,最重要的条件是看是不是一个类加载器:
写一个代码:
package org.dreamtech.cl; import java.io.IOException; import java.io.InputStream; public class ClassInit { //自定义类加载器 public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { ClassLoader loader = new ClassLoader() { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { try { String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class"; InputStream is = getClass().getResourceAsStream(fileName); if (is == null) { return super.loadClass(name); } byte[] b = new byte[is.available()]; is.read(b); return defineClass(name, b, 0, b.length); } catch (IOException e) { throw new ClassNotFoundException(); } } }; String className = "org.dreamtech.cl.ClassInit"; Object o1 = ClassInit.class.getClassLoader().loadClass(className).newInstance(); Object o2 = loader.loadClass(className).newInstance(); System.out.println(o1 == o2); System.out.println(o1.equals(o2)); System.out.println(o1 instanceof org.dreamtech.cl.ClassInit); System.out.println(o2 instanceof org.dreamtech.cl.ClassInit); System.out.println(o1.getClass().getClassLoader()); System.out.println(o2.getClass().getClassLoader()); } }
打印如下:
false false true false sun.misc.Launcher$AppClassLoader@18b4aac2 org.dreamtech.cl.ClassInit$1@14ae5a5
原文链接:https://www.cnblogs.com/xuyiqing/p/12468440.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 学习Java 8 Stream Api (4) - Stream 终端操作之 collect 2020-06-11
- java学习之第一天 2020-06-11
- JVM常见面试题解析 2020-06-11
- Java学习之第二天 2020-06-11
- Spring WebFlux 学习笔记 - (一) 前传:学习Java 8 Stream Ap 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash