Jvm 编译过程及双亲委派机制

一、基础知识


  1. Java从编码到执行

2、从跨平台的语言(java)到跨语言的平台(jvm)

3、JVM是一种规范,任何语言只要能编译成class文件,都能在jvm上运行

字节码指令集(汇编语言)

内存管理:栈、堆、方法区等

4、常见的JVM实现

JDK8以后的Hotspot JVM需要收费,Taobao VM免费

5、JDK JRE JVM

二、Class File Format


  • 二进制字节流

  • 数据类型: u1u2 u4 u8和_info(表类型)

  • _info的来源是hotspot源码中的写法

  • 查看16进制格式的ClassFile

  • sublime / notepad

  • IDEA插件-BinEd

  • 有很多可以观察ByteCode的方法:

  • iavap

  • JBE-可以直接修改

  • JClassLib -IDEA插件之一

  • class file 构成

  • classFile {u4magic;u2minor_version;u2major_version;u2constant_poo1_count;cp_info constant_poo7[constant_poo1_count - 1];u2}

三、Class Loading Linking Initializing 类加载-初始化


1、加载过程

(1)Loadding 把class文件load到内存(转成二进制字节)
(2)Linking
  1. verification

校验(是否符合Class文件的标准)

  1. preparation

class文件的静态变量赋默认值

  1. resolution

将类、方法、属性等符号引用解析为直接引用

常量池中的各种符号引用解析为指针,偏移量等内存地址的直接引用

(3)Initializing

调用静态代码块,静态成员变量赋初始值

2、类加载器

任何一个Class类 Load到内存之后,在内存中占了两块儿内容,一块儿是二进制字节码,另一块儿是Class类的对象,指向了对应的二进制字节码

通过对象去访问二进制文件,这个对象是在metespace(元空间)

启动类加载器(Bootstrap ClassLoader)
  1. 负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被

虚拟机认可(按文件名识别,如 rt.jar)的类。

扩展类加载器(Extension ClassLoader)
  1. 负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类

库。

应用程序类加载器(Application ClassLoader):
  1. 负责加载用户路径(classpath)上的类库。

JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader

实现自定义的类加载器。

3、双亲委派

一个孩子向父亲方向,然后父亲向孩子方向的双亲委派过程(双亲:从子到父,从父到子)

作用目的:安全。

主要问题:防止自定义类扰乱。

次要问题:不需要重新加载(防止资源浪费)

简介:

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object 对象。

4、类加载器的范围

5、自定义类加载器

自定义的类加载器可以用来加载自己加密后的class

/**
* 自定义类加载器
*/
publicclassZywClassLoaderextendsClassLoader{
​
    /**
     * 重写findClass方法
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protectedClass<?>findClass(Stringname) throwsClassNotFoundException {
        //类的绝对路径目录
        Filef=newFile("D:/develop/minnyouzi/src/main/java/com/example/zyw/entity",name.replaceAll(".","/").concat(".class"));
        try {
            FileInputStreamfis=newFileInputStream(f);
            //将文件转换为二进制字节数组
            ByteArrayOutputStreambaos=newByteArrayOutputStream();
            intb=0;
            //从文件中读出来写进字节数组
            while ((b=fis.read())!=0){
                baos.write(b);
            }
​
            byte [] bytes=baos.toByteArray();
            baos.close();
            fis.close();
​
            /**
             * 将二进制字节数组转换为类对象
             * name : 转换的类的名字
             * bytes:字节数组
             * off:字节数组起始的位置
             * bytes.length:结束的位置
             */
            returndefineClass(name,bytes,0,bytes.length);
        }catch (Exceptione){
            e.printStackTrace();
        }
​
        returnsuper.findClass(name);//throws ClassNotFoundException
​
    }
​
    publicstaticvoidmain(String[] args) throwsException{
        ClassLoaderl=newZywClassLoader();
        Classclazz=l.loadClass("com.example.zyw.entity.User");
        //通过反射访问
        Useruser= (User)clazz.newInstance();
        user.m();
        System.out.println(l.getClass().getClassLoader());
        System.out.println(l.getParent());
    }
}

  1. 编译

(1)混合模式

(2)lazyloading 懒加载

1.8之前

逻辑上:Method Area方法区:常量池、class各种信息

实际落地在永久代

1.8之后

metespace(元空间)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柚几哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值