总览
1.对象创建的过程 (半初始化)
2.DCL 是否需要 volatitle (指令重排)
3.对象内存结构(对象与数组的不同)
4.对象头包含什么 (markword klasspointer synchronized锁信息)
5.对象如何定位 (直接间接)
6.对象怎么分分配(栈 本地线程 eden old)
7.Obeject o = new Object()在内存中占多少字节
1.对象创建的过程 (半初始化)
public class T {
int m=8;
public static void main(string[] args){
T t = new T();
}
}
汇编码:
0 new #2<T> 申请内存 (半初始化 int 0)
3 dup 由于invoke
4 invokespecial # 3 <T.<init>> 设置初始值 调用T构造方法 0->8
7 astore_1 t和 内存对象关联
8return
2.DCL 是否需要 volatitle (指令重排)
单例模式 资源浪费(未使用 先new)
public class T {
private static final T INSTANCE=new T();
private T(){};
public static T getInstance(){ return INSTANCE;}
public void m(){ Systrm.out.println("m");}
public static void main(string[] args){
T t = T.getInstance();
T t1 = T.getInstance();
System.out.println(t == t1)
}
}
解决浪费按需初始化 , 线程不安全 多次new,
public class T {
private static T INSTANCE;
private T(){};
public static T getInstance(){
// 按需初始化
if (INSTANCE == null ){
try {
Thread.sleep(millis: 1);
} catch (InterruptedException e){
e.printStackTrace();
}
INSTANCE = new T();
}
return INSTANCE;
}
public void m(){ Systrm.out.println("m");}
public static void main(string[] args){
for(int i=0; i<100;i++){
new Thread(()->
System.out.println(T.ggetInstance().hashCode())
).start();
}
}
}
线程安全 锁整个方法 效率下降
public class T {
private static T INSTANCE;
private T(){};
// syncnronized
public static syncnronized T getInstance(){
if (INSTANCE == null ){
try {
Thread.sleep(millis: 1);
} catch (InterruptedException e){
e.printStackTrace();
}
INSTANCE = new T();
}
return INSTANCE;
}
public void m(){ Systrm.out.println("m");}
public static void main(string[] args){
for(int i=0; i<100;i++){
new Thread(()->
System.out.println(T.ggetInstance().hashCode())
).start();
}
}
}
锁整内部方法
public class T {
private static T INSTANCE;
private T(){};
public static T getInstance(){
if (INSTANCE == null ){
//通过减小同步代码快的方式提高效率 ,可能第一个Thread判断完了 等在这,
//第二个Tread 判断完往下走,已经给T赋值了,第一个再往下走重新newT
syncnronized (T.class){
try {
Thread.sleep(millis: 1);
} catch (InterruptedException e){
e.printStackTrace();
}
INSTANCE = new T();
}
}
return INSTANCE;
}
public void m(){ Systrm.out.println("m");}
public static void main(string[] args){
for(int i=0; i<100;i++){
new Thread(()->
System.out.println(T.ggetInstance().hashCode())
).start();
}
}
}
DCL Double Check Lock CPU指令重排序 之后 读取之前半初始化的值(volatile 保持Thread可见性,禁止指令重拍)
public class T {
private static volatile T INSTANCE; 禁止指令重排
private static T INSTANCE;
private T(){};
public static T getInstance(){
//业务代码省略
if (INSTANCE == null ){ //DCL
//双重检查
syncnronized (T.class){
if(INSTANCE == null){
try {
Thread.sleep(millis: 1);
} catch (InterruptedException e){
e.printStackTrace();
}
INSTANCE = new T();
}
}
}
return INSTANCE;
}
public void m(){ Systrm.out.println("m");}
public static void main(string[] args){
for(int i=0; i<100;i++){
new Thread(()->
System.out.println(T.ggetInstance().hashCode())
).start();
}
}
}
DCL指令重排
4对象内存结构(对象与数组的不同)
markword +class pointer =object header
image.png
打印对象信息
import org.openjdk.jol.info.ClassLayout;
public class HelloJOL{
public static void main(String[] args){
object o =new Object();
String s =ClassLayout.parseInstance(o).toPrintable();
System.out.println(s);
syncnroized(o){
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
}
}
syncronized:
锁升级:
偏向锁-->自旋锁(CAS)-->重量锁
偏向锁
贴标签 是我的标签直接使用内存
不是我的 CAS竞争
CAS
CAS
重量锁
放到os队列中 轮到你才执行(之前的都在jvm里)
5.对象如何定位 (直接间接)
对象如何定位6.对象怎么分分配(栈 本地线程 eden old)
对象如何分配标量替换:用成员变量即可代表这个对象
逃逸: 创建的对象只能自己用,别的方法调用不到
(jvm默认开启 上边两个)
禁用标量替换和逃逸 效率下降一半 TLAB buffer
Eden区给每个Thread 分配了一段专属内存 没有锁
符合TLAB的直接房专属内存
7.Obeject o = new Object()在内存中占多少字节
o oop 4个
obeject
类压缩,对象压缩
网友评论