死磕深入理解java虚拟机2--第七章笔记

中间跳了几章,过些天(有可能是很多天)会补充回来


重温深入理解java虚拟机这本书,温故而知新。

书是基于java虚拟机规范而来,文章中会掺杂我的个人理解的描述,如有误,请指正。

1、类加载的时机

死磕深入理解java虚拟机2--第七章笔记_第1张图片
类生命周期

说明:类加载过程规范中并没有进行强制约束,具体实现自由把握。

初始化在有且只有此5种情况下必须被初始化。

A、遇到new、getstatic、putstatic或invokestatic字节码指令:使用new关键字、读取或设置类的静态字段(被final修饰,已在编译期把结果放入常量池的静态字段除外)、调用类的静态方法

B、java.lang.reflect包的方法进行反射

C、初始化类时候,发现父类没初始化,先初始化父类(接口除外)

D、虚拟机启动执行的主类

E、jdk1.7之后动态语言支持

2、类加载过程详解

(1)加载:拿到class文件,可以从网络、zip包、文件夹都可以。

(2)验证:文件格式、元数据、字节码、符号引用等的验证

(3)准备:正式为类变量(被static修饰的)分配内存并设置类变量初始值(被static修饰的基本类型 int为0)阶段,如果static final修饰,则直接为对应的值,比如public static final int value=321  这个阶段直接就是321,而不会是初始值0了。

(4)解析:a、类或接口的解析 b、字段解析 c、类方法解析 d、接口方法解析

(5)初始化(字节码开始内容开始登场):

A、编译为class文件后,会把静态代码块、静态变量生成方法(类变量的赋值动作和static{}语句块),这里还有一个问题,就是静态代码块中的变量不能引用静态代码块后面声明变量,可以打印使用,不能赋值。详情见:https://blog.csdn.net/zhoumingsong123/article/details/82120362

B、虚拟机保证先执行父类的,也就是一定先执行Object的

C、类或接口不是必须的,如果没有静态语句,也没有对变量进行的赋值操作

D、接口如果不存在静态语句块,则子类或者实现初始化时,不需要调用父接口的方法。

F、虚拟机保证多线程加载的时候是线程安全的,只会有一个线程执行一次。

3、类加载器(上面是理论,这个是实现)

不同的类加载器加载的同一个class文件,在instanceof进行判断时候是不相同的。

双亲委派模型:不是强制行的,而是推荐的形式

(1)启动类加载器(Bootstrap ClassLoader):加载/lib目录中或者被-Xbootclasspath参数指定的路径,并且仅文件名识别rt.jar。

(2)扩展类加载器(Extension ClassLoader,sun.misc.Launcher$ExtClassLoader):加载/lib/ext或者java.ext.dirs指定的类库,开发者可以使用

(3)应用程序类加载器(Application ClassLoader,sun.misc.Launcher$AppClassLoader):加载类路径上的指定的类库

(4)自定义类加载器(虽然能随便加载类,但是加载以java.lang开头的类不会成功)

破坏双亲委派的情况:

(1)写自定义类加载的时候,可能会覆盖loadClass方法,这只是为了兼容1.2之前的逻辑,所以不建议自己覆盖此方法,应该覆盖findClass,这样loadClass加载不了的类再调用自定义的findClass方法进行寻找加载,实现完美的双亲委派模型。

(2)类似JNDI服务,需要父类用到自定义加载器加载的资源,使用线程上下文解决。

(3)程序的动态性,比如热部署、模块热部署等。例如OSGI模块化做的工作。

你可能感兴趣的:(死磕深入理解java虚拟机2--第七章笔记)