java 编译到执行 x.java -> javac -> x.class classLoader
class File Format 是二进制字节流
数据类型:u1 u2 u4 u8 _info
class 文件结构,版本号 Magic (cafe babe) ,Major Version 常量池 congstant_pool_count, access_public 是一写标志按位与的结果
this_class superclass , fileds, interface_count , medthod ,medthod _count atrribute
idea 插件jclasslib 用来查看二进制和代表的意思
类的加载和初始化
loading - linking - initializing
linking 分三个 : verification 看符不符合规格,例如字节码开头是不是cafababe
preparation 给一些静态变量赋值默认初始值,后续在initializing 会给初始值
resolution 在二进制里面的符号的引用 0030 这种,转成地址的引用
class load 是两个操作,一是二进制放进内存,二是创建一个class的引用指向内存
不同层的类加载器 :boostrap lib/rt.jar charset.jar 等核心类 是 c++ 写的(String.class)class.getClassLoader() 打印是空,Extension 加载扩展包,jre/lib/ext/*.jar,
App classpath指定内容 , custom classLoader 自定义类加载器
父加载器不是继承关系,
双亲委派,当一个类需要加载的时候,自底向上,查看缓存,没有就检查上一层缓存,到了bootstrap 依然没有查询到,就向下找复合的loader
为何双亲委派,为了安全,不能是自定义的loader 去load 基础的。
如何打破双亲委派:1.jdk1.2之前没有findClass方法,只能重写classLoader() 2. ThreadContextClassLoader可以实现基础类调用通过制定线程上下文
3. sogi,tomcat,热部署,糊自定义classLoader
类加载器的范围
自定义类加载器 继承classLoader方法
loadClass() 过程要syn 枷锁,然后要先判断是否已经加载过,没有就this.parent.loadClass() ,双亲委派
parent final的 改不了,最后是执行 findClass(),自定义要实现findClass方法
中间处理,最后defineClass (name,bytes,s,e)
编译器:混合模式使用解释器和热点代码编译,起始的时候,使用解释执行,热点代码检测,被调用很多次就进行编译,可以指定模式,编译模式启动慢,执行快,解释,反之。
懒加载:lazyInitializing 没有要求什么时候加载,但是严格要求什么时候初始化
1. final , new , getstatic 2.反射 3.加载子类,必先加载父类 4.加载主要的类 5.动态语言支持 invoke.MethodHandle