- 前言
- 类文件格式
- 类加载器
- 运行时数据区
- 资源
前言
基于 JDK 8
类文件格式The class File Format
Java 之所以可以“一次编译,到处运行”,一是因为 JVM 针对各种操作系统、平台都进行了定制;二是因为无论任何平台,javac 编译生成固定格式的字节码文件(*.class)供 JVM 使用。
格式:
- 魔数(Magic)
- 版本号(Version)
- 常量池(constant_pool)
- 访问标志(access_flag)
- 当前类索引(this_class)
- 父类索引(super_class)
- 接口索引(interfaces)
- 字段表(fields)
- 方发表(methods)
- 附加属性(attributes)
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count - 1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
类加载器
# 监控类的加载 -XX:+TraceClassLoading -XX:+TraceClassUnloading
Creation and Loading
要执行 class 文件就需要先将其读入内存,这个是由类加载器完成的。
类加载器类型:
| 名称 | 说明 |
|---|---|
| Bootstrap ClassLoader | C++ 实现,无法访问 |
| Extension ClassLoader | 父类为 Bootstrap,显示为 null |
| Application ClassLoader | 父类为 Extension |
| 自定义 ClassLoader | 父类为 Application |
package xianzhan.jdk8;
public class Main {
public static void main(String[] args) {
LeeClassLoader loader = new LeeClassLoader();
System.out.println(loader.getClass().getName());
ClassLoader p = loader.getParent();
while (p != null) {
System.out.println(p.getClass().getName());
p = p.getParent();
}
}
}
class LeeClassLoader extends ClassLoader {
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
System.out.println("重写该方法. name: " + name);
return super.findClass(name);
}
}
运行时数据区
# 设置线程栈大小,限制栈的深度 -Xss1M # 逃逸分析 # 开启逃逸分析 JDK 1.6 默认开启 -XX:+DoEscapeAnalysis # 查看逃逸分析的筛选结果 -XX:+PrintEscapeAnalysis # 元空间 # 设置分配的 Metaspace 的大小,Metaspace 将在首次超过垃圾收集时触发垃圾收集。 # 垃圾收集的阈值取决于使用的元数据量而增加或减少。默认大小取决于平台。 -XX:MetaspaceSize=size # 设置可以分配给 Metaspace 的最大本机内存。默认情况下,大小不受限制。 # 应用程序的 Metaspace 量取决于应用程序本身,其他正在运行的应用程序以及系统上可用的内存量 -XX:MaxMetaspaceSize=size # 堆 # JVM 启动时, 所占据的操作系统内存的大小 -Xms2G -XX:InitialHeapSize=2G # 最大堆是指新生代和老年代的大小之和的最大值 # 它是 Java 应用程序的堆上限 -Xmx2G -XX:MaxHeapSize=2G # 用于设置新生代的大小 # 新生代越大, 老年代越小 # 新生代一般设置为整个堆空间的 1/4 到 1/3 左右 -Xmn512M # -Xmn 的效果等同于设置了相同的 -XX:NewSize 和 -XX:MaxNewSize # 下面参数不一致时, 可能会导致内存震荡, 从而导致不必要的开销 # 设置新生代的初始大小 -XX:NewSize # 设置新生代的最大值 -XX:MaxNewSize # 设置新生代中, eden 空间和 s0 空间的比例关系 # -XX:SurvivorRatio=eden/s0=eden/s1 -XX:SurvivorRatio=8 # 设置 survivior 区的可使用率 # 当 survivior 区的空间使用率达到这个数值时, 会将对象送入老年代 -XX:TargetSurvivorRatio # 设置新生代和老年代的比例 # -XX:NewRatio=老年代/新生代 -XX:NewRatio=2 # 设置堆空间的最小空闲比例 # 当堆空间的空闲内存小于这个数值时, JVM 便会扩展堆空间 -XX:MinHeapFreeRatio # 设置堆空间的最大空闲比例 -XX:MaxHeapFreeRatio
java
Run-Time Data Areas
JEP 122: Remove the Permanent Generation
JEP 147: Reduce Class Metadata Footprint
JEP 149: Reduce Core-Library Memory Usage
JDK 8 运行时数据区里的方法区,由之前的永久代(Permanent Generation)改为元空间(Metaspace)。
资源JVM 规范



