new 对象的过程:申请内存空间->默认值->初始值
这里有可能发生指令重排 出现半初始化状态 DCL单例为什么要加volatile的答案(new Instance会出现问题)

协议很多
intel 用MESI
https://www.cnblogs.com/z00377750/p/9180644.html
现代CPU的数据一致性实现= 缓存锁(MESI ...) + 总线锁
读取缓存以cache line为基本单位,目前64bytes
位于同一缓存行的两个不同数据,被两个不同CPU锁定,产生互相影响的伪共享问题
使用缓存行的对齐能够提高效率(disruptor 框架就是利用了这一点)
CPU乱序执行的问题:如果没有直接依赖关系 为了提高效率 在一条指令执行的过程中(读数据慢100倍),去同时执行另外一条指令
WCBuffer(4个位置):写操作也可以进行合并(放在WCBuffer执行)
案例:
packagecom.mashibing.juc.c_029_WriteCombining;
public final class WriteCombining {
private static final int ITERATIONS = Integer.MAX_VALUE;
private static final int ITEMS = 1 << 24;
private static final int MASK = ITEMS - 1;
private static final byte[] arrayA = new byte[ITEMS];
private static final byte[] arrayB = new byte[ITEMS];
private static final byte[] arrayC = new byte[ITEMS];
private static final byte[] arrayD = new byte[ITEMS];
private static final byte[] arrayE = new byte[ITEMS];
private static final byte[] arrayF = new byte[ITEMS];
public static void main(final String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println(i + " SingleLoop duration (ns) = " +runCaseOne());
System.out.println(i + " SplitLoop duration (ns) = " + runCaseTwo());
}
}
public static long runCaseOne() {
long start = System.nanoTime();
int i = ITERATIONS;
while (--i != 0) {
int slot = i & MASK;
byte b = (byte) i;
arrayA[slot] = b;
arrayB[slot] = b;
arrayC[slot] = b;
arrayD[slot] = b;
arrayE[slot] = b;
arrayF[slot] = b;
}
return System.nanoTime() - start;
}
public static long runCaseTwo() {
long start = System.nanoTime();
int i = ITERATIONS;
while (--i != 0) {
int slot = i & MASK;
byte b = (byte) i;
arrayA[slot] = b;
arrayB[slot] = b;
arrayC[slot] = b;
}
i = ITERATIONS;
while (--i != 0) {
int slot = i & MASK;
byte b = (byte) i;
arrayD[slot] = b;
arrayE[slot] = b;
arrayF[slot] = b;
}
return System.nanoTime() - start;
}
}JVM内存屏障(有序性)硬件层内面上的实现并不一定是依赖硬件级别内存屏障实现还可以依赖硬件级别的lock指令
硬件CPU内存屏障
sfence: store| 在sfence指令前的写操作当必须在sfence指令后的写操作前完成。
lfence:load | 在lfence指令前的读操作当必须在lfence指令后的读操作前完成。
mfence:modify/mix | 在mfence指令前的读写操作当必须在mfence指令后的读写操作前完成。
JVM级别如何规范(JSR133):
LoadLoad屏障
对于这样的语句Load1;LoadLoad; Load2,
在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
StoreStore屏障:
对于这样的语句Store1;StoreStore; Store2,
在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
LoadStore屏障:
对于这样的语句Load1;LoadStore; Store2,
在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
StoreLoad屏障: 对于这样的语句Store1; StoreLoad;Load2,
在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。
Volatile的实现细节:
1. 字节码层面:
ACC_VOLATILE
2. JVM层面:
Volatile内存区的读写都加屏障
StoreStoreBarrier
volatile 写操作
StoreLoadBarrier
LoadLoadBarrier
volatile 读操作
LoadStoreBarrier
3. OS和硬件层面
https://blog.csdn.net/qq_26222859/article/details/52235930
hsdis- HotSpot Dis Assembler
windows lock 指令实现 | MESI实现
synchronized实现细节:
1. 字节码层面:
ACC_SYCHRONIZED
moitorenter monitorexit(2个)

2. JVM层面
C++调用了操作系统提供的同步机制
3. OS和硬件层面
X86 : lock cmpxchg / xxx
https://blog.csdn.net/21aspnet/article/details/88571740
对象的创建过程:
1. classloading
2. classlinking(verification preparation resolution)
3. classinitializing
4. 申请对象内存
5. 成员变量赋默认值
6. 调用构造方法<init>
成员变量顺序赋初始值
执行构造方法语句
对象在内存的存储布局:
首先查看自己虚拟机的配置:java-XX:+PrintCommandLinesFlags -version
红色的参数就是内存布局

对象的内容(对象的内存部局也可以这么说):
普通对象
1. 对象头markword8
2. ClassPointer指针 XX:+UseCompressedClassPointers 为4字节 不开启为8字节
3. 实例数据引用类型:-XX:+UseCompressedOops为4字节 不开启为8字节Oops Ordinary Object Pointers
4. Padding对齐 8的倍数
数组对象:
1. 对象头markword8
2. ClassPointer指针 XX+UserCompresseddClassPointer为4字节 不开启为8字节
3. 数组长度:4字节
4. 数组数据
5. 对其8的倍数
首先一个class load到内存的时候有一个agent 来截获或者修改 需要自己实现它(premain 方法) 相当于代理
实验:
1. 新建项目ObjectSize(1.8)
2. 创建文件ObjectSizeAgent
packagecom.mashibing.jvm.agent;
importjava.lang.instrument.Instrumentation;
public classObjectSizeAgent {
private static Instrumentation inst;
public static void premain(StringagentArgs, Instrumentation _inst) {
inst = _inst;
}
public static long sizeOf(Object o) {
return inst.getObjectSize(o);
}
}3. src目录下创建META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: mashibing.com
Premain-Class:com.mashibing.jvm.agent.ObjectSizeAgent
注意Premain-Class这行必须是新的一行(回车 + 换行),确认idea不能有任何错误提示
4. 打包jar文件
5. 在需要使用该AgentJar的项目中引入该Jar包 project structure- project settings - library 添加该jar包
6. 运行时需要该AgentJar的类,加入参数:
-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar
7. 如何使用该类:
packagecom.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(newP()));
}
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
}
}Object 16字节
Int 16字节
// -XX:+UseCompressedClassPointers-XX:+UseCompressedOops 这两个是分开的
// Oops = ordinary object pointers
Hotspot开启内存压缩的规则(64位机):
1. 4G以下,直接砍掉高32位
4G - 32G,默认开启内存压缩ClassPointers Oops (ordinary object pointers)
2. 32G,压缩无效,使用64位 内存并不是越大越好(^-^)
对象头具体包含什么:
具体看对象的状态


当一个对象计算过identityHashCode之后,不能进入偏向锁状态