这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
对象的创建过程
- class loading
- class linking(verification、preparation、resolution)
- class initializing
- 申请/分配 对象内存
- 成员变量赋默认值
- 调用构造方法
- 成员变量顺序赋初始值
- 执行构造方法语句
前三步是在类加载过程中完成
对象在内存中的存储布局
观察虚拟机配置
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=132670528 -XX:MaxHeapSize=2122728448 -XX:+PrintCommandLineFlags -XX:>+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
普通对象
-
对象头:markword 8字节
-
ClassPointer指针:-XX:+UseCompressedClassPointers 为4字节 不开启为8字节
-
实例数据 引用类型:-XX:+UseCompressedOops 为4字节 不开启为8字节
Oops Ordinary Object Pointers(普通对象指针String等)
- Padding对齐,8的倍数
数组对象
- 对象头:markword 8
- ClassPointer指针同上
- 数组长度:4字节
- 数组数据
- 对齐 8的倍数
实验(查看对象在内存中占多少字节)
class文件load到内存的过程中能够被agent(代理)截获信息进行修改
-
新建项目ObjectSize (1.8)
-
创建文件ObjectSizeAgent
package com.mashibing.jvm.agent;
import java.lang.instrument.Instrumentation;
public class ObjectSizeAgent {
private static Instrumentation inst;
//jvm调用(固定格式)
public static void premain(String agentArgs, Instrumentation _inst) {
inst = _inst;
}
//自定义方法
public static long sizeOf(Object o) {
return inst.getObjectSize(o);
}
}
- src目录下创建META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: mashibing.com
Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent
注意Premain-Class这行必须是新的一行(回车 + 换行),确认idea不能有任何错误提示
-
在需要使用该Agent Jar的项目中引入该Jar包 project structure - project settings - library 添加该jar包
-
运行时需要该Agent Jar的类,加入参数:
-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar
7. 如何使用该类:
package com.mashibing.jvm.c3_jmm;
import com.mashibing.jvm.agent.ObjectSizeAgent;
public class T03_SizeOfAnObject {
public static void main(String[] args) {
System.out.println(ObjectSizeAgent.sizeOf(new Object()));
System.out.println(ObjectSizeAgent.sizeOf(new int[] {}));
System.out.println(ObjectSizeAgent.sizeOf(new P()));
}
//一个Object占多少个字节
// -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
// Oops = ordinary object pointers
private static class P {
//8 _markword
//4 _oop指针
int id; //4
String name; //4
int age; //4
byte b1; //1
byte b2; //1
Object o; //4
byte b3; //1
}
}
Hotspot开启内存压缩的规则(64位机)
1. 4G以下,直接砍掉高32位 2. 4G - 32G,默认开启内存压缩 ClassPointers Oops 3. 32G,压缩无效,使用64位 内存并不是越大越好(^-^)
IdentityHashCode的问题
当一个对象计算过identityHashCode之后,不能进入偏向锁状态\
cloud.tencent.com/developer/a…
cloud.tencent.com/developer/a…
cloud.tencent.com/developer/a…
cloud.tencent.com/developer/a…
对象定位
- 句柄池
- 直接指针
对象头具体包括什么
markword 64位
下面的图是32位的,64位的与之类似
- hashCode部分:
问题:为什么GC年龄默认为15?(最大为15)
答:分代年龄占4bit,能表示的区间0-15