JVM02_类加载器子系统、类加载过程

内存结构

在这里插入图片描述
堆区和方法区是线程共享的

类加载子系统

在这里插入图片描述
JVM不管你的字节码文件是通过什么语言编写的,只要生成的字节码文件符合JVM的规范,那么就可以执行。
类加载器负责把字节码文件加载到内存,是否可以运行,由执行引擎来决定。
在这里插入图片描述

类加载过程

在这里插入图片描述

1、加载阶段(区别于整体的类加载)

掌握:类加载器通过全限定类名获取类的二进制字节流。生成类的Class对象是在这个阶段出现的。
在这里插入图片描述
在这里插入图片描述

2、链接阶段

在链接阶段中的准备阶段,只会给类变量分配内存并设置初始值,到了初始化阶段才会赋给它实际定义的值
在这里插入图片描述
而对于final类型的static变量,实际是一个常量,它在编译成class文件的编译期就已经分配内存了,这里的准备阶段只是确定地显式说明一下。
当然,实例变量也不会在准备阶段初始化,因为对象还没有产生。
类变量会分配到方法区,实例变量会随对象分配到java堆
在这里插入图片描述
通过Binary Viewer工具查看class文件
一个JVM能运行的class文件都是以CAFEBABE开头的
在这里插入图片描述

3、初始化阶段,理解记忆

clinit类的构造器方法,区别于java类中的构造器
clinit不需要程序员定义。是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并来的。
构造器中指令按源文件中出现顺序执行。
在这里插入图片描述
使用Binary Viewer 把字节码文件打开,这其中的字节码一个个翻译后就是ByteCode viewer的结果
在这里插入图片描述
在这里插入图片描述
类成员number声明在下边,赋值在上边,这种写法也是可以的
因为:在链接阶段的准备环节,就给static类成员进行了分配内存并赋值为0,然后才从上到下赋值并覆盖,最终结果是10
在这里插入图片描述
在这里插入图片描述
变量number的声明发生在后边,在前边的静态代码块中可以赋值,但是不可以调用
在这里插入图片描述
下边代码,因为此时没有类成员和静态代码块,所以不需要clinit,所以不产生clinit
在这里插入图片描述
在这里插入图片描述
此时如果加上一个类成员
在这里插入图片描述
就产生clinit方法.
所以说clinit只有在存在类成员的时候才会出现,只负责出final修饰的静态成员和静态代码块
在这里插入图片描述
上边就是构造器方法
子类的加载是在父类加载后
在这里插入图片描述
在多线程下,一个类只能被加载一次
在这里插入图片描述
在这里插入图片描述

上边代码,两个线程,2先抢到,在执行到DeadThread类时出现死循环,一直跳不出,那线程1就没法进行,也就是说,DeadThread类只被加载了一次。在操作这个对象的时候存在一个锁的过程,只能由一个线程操作

加载同一个线程,会导致其他线程出现阻塞的状态,要避免

重新理解这个类加载过程
在这里插入图片描述

面试能说清楚类加载过程中每个阶段的主要操作就可以

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值