性能优化专题共计四个部分,分别是:
本节是性能优化专题第三部分 —— JVM 性能优化篇,共计六个小节,分别是:
通过这六节的学习,你将学到:
➢ 了解JVM内存模型以及每个分区详解。
➢ 熟悉运行时数据区,特别是堆内存结构和特点。
➢ 熟悉GC三种收集方法的原理和特点。
➢ 熟练使用GC调优工具,快速诊断线上问题。
➢ 生产环境CPU负载升高怎么处理?
➢ 生产环境给应用分配多少线程合适?
➢ JVM字节码是什么东西?
• 给对象分配内存
• 线程安全性问题
• 初始化对象
• 执行构造方法
指针碰撞和空闲列表
• 线程同步
解析JVM线程同步机制
• 本地线程分配缓冲(TLAB)
Thread Local Allocation Buffer(本地分配缓存区)
每一个对象都由对象头、对象的实例数据区和对齐填充字节这三部分组成。
相同宽度的数据分配到一起(long,double)
8个字节的整数倍
• 使用句柄
• 直接指针
JVM 中对象的访问定位
逃逸分析(Escape Analysis)与栈上分配
class Person{
private String name;
private int age;
private static String address;
private final static String hobby="Programming";
public void say(){
System.out.println("person say...");
}
public int calc(int op1,int op2){
return op1+op2;
}
}
现在我们对 Person.java 类编译的得到 Person.class 字节码文件:
javac Person.java
Person.java -> 词法分析器 -> tokens流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器-> 注解抽象语法树 -> 字节码生成器 -> Person.class文件
Class 文件是一组以 8 位字节为基础单位的二进制流,各个数 据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加 任何分隔符,这使得整个 Class 文件中存储的内容几乎全部是程序 运行的必要数据,没有空隙存在。
当遇到需要占用 8 位字节以上空间的数据项时,则会按照 高位在前(Big-Endian)的方式分割成若干个 8 位字节进行存储。
Class 文件只有两种数据类型:
我们刚才通过java文件反编译成了class字节码文件,那么我们怎么通过字节码编译成java文件呢?
实际上jvm就帮助我们做了这样的事情,那么jvm具体是怎么实现的呢?如果我们不借助jvm,怎么可以破解这样的二进制字节码文件?
Oracle官网(开源JDK的厂商)关于Class文件的描述
magic(魔数):
The magic item supplies the magic number identifying the class file format; it has the
value 0xCAFEBABE .
我们注意到字节码的开头是
cafe babe
通过官网查的,此为固定写法。
接着我们看:
0000 0034
通过官网文档得知:
minor_version, major_version
所以我们知道了 这两位16进制的数字就对应10进制的52,代表JDK 8中的一个版本。
接着看:
0027
官网查得 constant_pool_count
说明是 对应十进制27,代表常量池中27个常量
等等依次类推,这里不再细说,有兴趣的可以参考Oracle官方文档对于类文件的解析:
魔数版本
JDK1.8 = 52
JDK1.8 = 51
格式:
cp_info {
u1 tag;
u1 info[];
}
访问标志
类索引,父类索引,接口索引集合
字段表集合 :字段表用于描述接口或者类中声明的变量
方法表集合
属性表集合
整体结构如下:
ClassFile {
u4 magic; // 魔法数字,表明当前文件是.class文件,固定0xCAFEBABE
u2 minor_version; // 分别为Class文件的副版本和主版本
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]; // 各种属性
}
javap -c Person.class > Person.txt
Compiled from "Person.java"
class com.testjvm.Person {
com.testjvm.Person();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public void say();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String person say...
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
public int calc(int, int);
Code:
0: iload_1
1: iload_2
2: iadd
3: ireturn
}
本节代码下载地址为:https://github.com/harrypottry/jvmDemo
更多架构知识,欢迎关注本套系列文章:Java架构师成长之路