前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jvm的类加载过程

jvm的类加载过程

原创
作者头像
是小张啊喂
修改2021-02-22 18:01:49
7100
修改2021-02-22 18:01:49
举报
文章被收录于专栏:软件软件

java类加载过程

classLoader
classLoader

JVM将类的加载过程分为三个步骤:装载(Load)链接(Link)和初始化(Initialize)

1、装载

通过一个类的全限定类名获取类的二进制字节流

将在这个字节流代表的静态存储结果转化为方法区的运行时内存

2、链接

验证:确保被加载类的正确性

​ 主要包括四种验证:文件格式验证、元数据验证、字节码验证、符号引用验证

准备:为类的静态变量分配内存,并将其初始化为默认值

(不包含被final修饰的static,因为final在编译的时候就会分配,准备阶段会显示的初始化)

解析:把常量池中的符号引用转换为直接引用

3、初始化

为类的静态变量赋予正确的初始值

实例查看类加载器

代码语言:javascript
复制
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
    }
}
代码语言:javascript
复制
// 运行结果
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)(如果一个类加载器收到了类加载请求,它并不会自己先去加载。而是会把这个请求委托给父类的加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,以此递归。如果父类加载器可以完成类加载任务,就成功返回,如果父类加载器无法完成此加载任务,子加载才会尝试自己去加载)

Parents Delegation model
Parents Delegation model

即:向上委托查找,向下委托加载

  1. Bootstrap ClassLoader(启动类加载器)负责装载最核心的Java类 使用C++语言实现,嵌套在JVM 内部,并不集成java.lang.ClassLoader没有父加载器 加载拓展类和应用程序类加载器,并指定他们为父类加载器 启动类加载器只加载包名为javajavax和``sun`等开头的类
  2. Extension ClassLoader(扩展类加载器) 派生于ClassLoader类 ,父类加载器为Bootstrap ClassLoader(启动类加载器)
  3. 应用程序类加载器(Application ClassLoader)

自定义类加载器

在什么情况下 需要自定义的加载器? 1、隔离加载器 2、修改类加载方式 3、拓展加载类 4、防止源码泄露

自定义实现类加载器

代码语言:javascript
复制
// JDK 类加载对象
// classLoader -> SecureClassLoader -> URLClassLoader -> ExtClassLoader,AppClassLoader

将下面的放法打成jar,目的是模拟防止源码泄露。

代码语言:javascript
复制
public String url(String url) {
    String login = "/login" + url;
	return login;
}

idea如何将Java文件打成Jar? jar -cvf 【打包后的文件名】.jar 【要打包的目录】

代码语言:javascript
复制
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();
} 
代码语言:javascript
复制
/login/submit

JVM注定将是一条不归路,硬着头皮往前冲吧!

如果对编程感兴趣,请关注我的个人博客 https://www.lzmvlog.top/ ,谢谢

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • java类加载过程
    • 实例查看类加载器
      • 自定义类加载器
        • 自定义实现类加载器
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档