Java 类型的加载和链接都是在运行期间,这样可能会有性能开销,可是却能提供动态扩展的语言特性。
git
解析可能在初始化以后进行数组
vm规范规定了四个点必须对类进行初始化:网络
- 遇到new ,getstatic,putstatic, invokestatic几个指令的时候。也就是new, 使用设置静态变量,引用静态方法的时候 访问静态变量只会形成当前类的初始化,不会初始化子类,这里还要注意,对于被final修饰、在编译器已经放入常量池的静态属性不会触发初始化。 new 数组是不会初始化类的
- reflect包的方法对类进行反射调用的时候
- 初始化时要先初始化父类
- 虚拟机启动时要指定主类,主类会先初始化
过程
加载
1. 根据全名获取二进制字节流 没有指明流的来与,因而能够是jar包,网络,动态代理在运行时生成
2. 在方法区生成该类的运行时数据结构
3. 在堆上建立Class对象,做为对方法区数据访问入口
验证
要求知足字节码格式规范等
准备
为类变量分配内存并设定初始值的阶段, 不涉及实例变量,都在方法区进行。
解析
将常量池内的符号引用替换为直接引用的过程。
符号引用就是字面量, 没有指向实际的内存,只是表示知道这个类有这个引用,但具体引用到哪里还不知道
直接引用, 是链接了实际目标的符号引用
初始化
执行类client()方法的过程, 由编译器收集的类变量赋值动做和static方法块合并成的。
虚拟保证client是顺序执行的,所以要注意若是static预发快中有死循环会形成阻塞
类加载器

- 工做流程: 收到加载请求后,交给父加载器去完成, 父完不成才会尝试本身完成。 以下是个过程 Class c = findClass(name); if(c == null){ c = parent.loadClass(name); } if(c == null){ // 父不行了,本身来 c = findClass(name) } return c;
- 破坏双亲委派
- JNDI 双亲委派解决不了基础类须要调用用户代码的状况 JNDI服务由启动加载器加载,可是其用到的接口类却由各个厂商提供,启动加载器就会找不到,引入了线程上下文加载器,须要使用Thread.setContextClassLoader()进行设置。JNDI就是用了这个加载器
- OSGI, 每一个boundler一个类加载器,import的类委托给export的类加载器去加载。