java
类加载过程JVM
将类的加载过程分为三个步骤:装载(Load)、链接(Link)和初始化(Initialize)
1、装载
通过一个类的全限定类名获取类的二进制字节流
将在这个字节流代表的静态存储结果转化为方法区的运行时内存
2、链接:
验证:确保被加载类的正确性
主要包括四种验证:文件格式验证、元数据验证、字节码验证、符号引用验证
准备:为类的静态变量分配内存,并将其初始化为默认值
(不包含被final
修饰的static
,因为final
在编译的时候就会分配,准备阶段会显示的初始化)
解析:把常量池中的符号引用转换为直接引用
3、初始化
为类的静态变量赋予正确的初始值
public class ClassLoaderDemo {
public static void main(String[] args) {
// 双亲委派模型
// 父子关系 Bootstrap ClassLoader -> ExtClassLoader -> AppClassLoader
ClassLoader classLoader1 = ClassLoaderDemo.class.getClassLoader();
System.out.println("classLoader1 -> " + classLoader1);
System.out.println("parent of classLoader1 -> " + classLoader1.getParent());
// Bootstrap ClassLoader 由 C++ 开发,是 jvm 的一部分,本身并不是java类
System.out.println("Grandfather of classLoader1 -> " + classLoader1.getParent().getParent());
// String 、Int 等基础类型由 Bootstrap ClassLoader 加载
ClassLoader classLoader2 = String.class.getClassLoader();
System.out.println("classLoader2 -> " + classLoader2);
try {
System.out.println(classLoader1.loadClass("java.util.List").getClass().getClassLoader());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// JDK 类加载对象
// classLoader -> SecureClassLoader -> URLClassLoader -> ExtClassLoader,AppClassLoader
}
}
// 运行结果
classLoader1 -> sun.misc.Launcher$AppClassLoader@18b4aac2
parent of classLoader1 -> sun.misc.Launcher$ExtClassLoader@39a054a5
Grandfather of classLoader1 -> null
classLoader2 -> null
null
Java
类加载的过程使用的是双亲委派模型(Parents Delegation model)
(如果一个类加载器收到了类加载请求,它并不会自己先去加载。而是会把这个请求委托给父类的加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,以此递归。如果父类加载器可以完成类加载任务,就成功返回,如果父类加载器无法完成此加载任务,子加载才会尝试自己去加载)
即:向上委托查找,向下委托加载
Bootstrap ClassLoader(启动类加载器)
负责装载最核心的Java
类
使用C++语言实现,嵌套在JVM 内部,并不集成java.lang.ClassLoader
没有父加载器
加载拓展类和应用程序类加载器,并指定他们为父类加载器
启动类加载器只加载包名为java
、javax
和``sun`等开头的类Extension ClassLoader(扩展类加载器)
派生于ClassLoader
类 ,父类加载器为Bootstrap ClassLoader(启动类加载器)
应用程序类加载器(Application ClassLoader)
在什么情况下 需要自定义的加载器? 1、隔离加载器 2、修改类加载方式 3、拓展加载类 4、防止源码泄露
// JDK 类加载对象
// classLoader -> SecureClassLoader -> URLClassLoader -> ExtClassLoader,AppClassLoader
将下面的放法打成jar
,目的是模拟防止源码泄露。
public String url(String url) {
String login = "/login" + url;
return login;
}
idea如何将Java文件打成Jar? jar -cvf 【打包后的文件名】.jar 【要打包的目录】
URL url = null;
try {
// 读取需要加载的文件
url = new URL("file:D:\\work\\design-mode\\ClassLoaderDemo.jar");
// 类加载器用于从引用JAR文件和目录的URL搜索路径中加载类和资源。假定所有以''结尾的URL均指目录。
// 否则,假定该URL指向将根据需要打开的JAR文件。 <p>在随后加载类和资源时将使用创建URLClassLoader实例的线程的AccessControlContext。
// 默认情况下,仅向加载的类授予权限,以访问创建URLClassLoader时指定的URL。
URLClassLoader loader = new URLClassLoader(new URL[]{url});
Class<?> aClass = loader.loadClass("top.lzmvlog.top.jvm.ClassLoaderDemo");
Object o = aClass.newInstance();
String newUrl = (String) aClass.getMethod("url", String.class).invoke(o, "/submit");
System.out.println(newUrl);
} catch (Exception e) {
e.printStackTrace();
}
/login/submit
JVM注定将是一条不归路,硬着头皮往前冲吧!
如果对编程感兴趣,请关注我的个人博客 https://www.lzmvlog.top/ ,谢谢
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。