从内存的层次分析类。
JAVA
内存- 堆
- 存放
new
的对象和数组 - 可以被所有的线程共享,不会存放别的对象引用
- 存放
- 栈
- 存放基本变量类型(会包含这个基本类型的具体数值)
- 引用对象的变量(会存放这个引用在对里面的具体地址)
- 方法区
- 可以被所有线程共享
- 包含了所有的
class
和static
变量
- 堆
类的加载过程
load
- 将类的
class
文件读入内存,并为之创建一个java.lang.Class
对象。此过程由类加载器完成
- 将类的
link
- 将类的二进制数据合并到
JRE
中 - 正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存将在方法区中进行分配
- 虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
- 将类的二进制数据合并到
Initialize
初始化JVM
负责对类进行初始化
1 | package com.redisc; |
输出
1 | 123 |
之所以 m 最后输出的是 300 是因为,代码块的顺序在下面。
如果顺序是
1 | static { |
则 m
的输出为 100
.
什么时候类初始化
- 类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化 main 方法所在的类
- new 一个类的对象
- 调用类的成员变量(除 final 变量)和静态方法
- 使用 java.lang.reflect 包的方法对类进行反射调用
- 初始化一个类,如果父类没有被初始化,则会先初始化它的父类
- 类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:通过字类引用父类的静态变量,不会导致字类初始化
- 通过数组定义类引用,不会出发此类的初始化
- 引用敞亮不会出发此类的初始化