JVM---对象

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
     *  【对象的实例化】
     *      <创建对象的方式>
     *          1、new
     *              a, new XXX
     *              b, XXX.static方法
     *              c, XXXBuilder/ XXXFactory的方法
     *          2、反射
     *              a, Class的newInstance
     *                  ***空参构造器,权限必须是public
     *              b, Constructor的newInstance
     *                  ***空参(或带参)构造器,权限不限制
     *          3、clone
     *              ***不调用构造器
     *                  当前类需要实现Cloneable接口,实现clone()
     *          4、反序列化
     *              从网络、文件中获取 一个对象的二进制字节流
     *          5、三方库Objenesis
     *              动态生成对象
     *
     *      <创建对象的步骤>
     *
     *              Object object = new Object();
     *
     *              0: new           #2                  // class java/lang/Object
     *              3: dup
     *              4: invokespecial #1                  // Method java/lang/Object."<init>":()V   对象成员变量显式初始化
     *              7: astore_1
     *              8: return
     *
     *
     *              1,判断对象对应的类是否加载、链接、初始化
     *                  当 JVM遇到new指令,首先去检查new指令的参数 能否在方法区的常量池中找到该类的引用,并检查该类是否被加载、链接、初始化:
     *                      如果没有,在双亲委派的模式下,使用当前类加载器查找对应的class文件:
     *                          若没有找到文件,抛出ClassNotFoundException;
     *                          找到文件,进行类加载;
     *
     *              2,计算 对象所占堆内存大小,然后在堆中分配内存给新对象;
     *                  如果 对象成员变量 是引用类型,只需要分配引用变量空间即可,4字节;
     *                      byte,short,int,char,boolean,float,引用类型 都是 4个字节;
     *                      double,long是8个字节;
     *
     *                  处理 内存分配 并发安全问题
     *                      1、使用CAS,保证操作的原子性
     *                      2、每个线程 预先 分配 一个 TLAB;
     *
     *              3,给 对象的实例属性 默认初始化;
     *
     *              4,设置 对象头
     *                  将对象的所属类、对象的hashcode、对象的GC信息、锁信息等 存储到对象头;
     *
     *              5,执行构造器<init>方法 进行 对象成员变量显式初始化(顺序执行):
     *                  aa,成员变量 显式 初始化;
     *                  bb,执行 实例代码块;
     *                  cc,执行 类的构造器;
     *                  dd,将 对象的地址 赋值给 引用变量
     *
     *
     *      <给对象属性赋值的操作>
     *          1、属性的默认初始化
     *          2、属性的显式初始化
     *              属性显式赋值、代码块显式赋值、构造器显式赋值...
     *
     *
     *      <类的构造器<init>方法>
     *          public class User {
     *
     *              private String name = "jack";
     *              private int age = 10;
     *
     *              {
     *                  name = "rose";
     *              }
     *
     *              public User(){
     *                  this.age = 11;
     *              }
     *
     *              public User(String name){
     *                  this.name = name;
     *              }
     *
     *              public User(int age){
     *                  this.age = age;
     *              }
     *          }
     *
     *          空参构造器<init>
     *              0 aload_0
     *              1 invokespecial #1 <java/lang/Object.<init>>
     *              4 aload_0
     *              5 ldc #2 <jack>
     *              7 putfield #3 <com/an/object/User.name>
     *              10 aload_0
     *              11 bipush 10
     *              13 putfield #4 <com/an/object/User.age>
     *              16 aload_0
     *              17 ldc #5 <rose>
     *              19 putfield #3 <com/an/object/User.name>
     *              22 aload_0
     *              23 bipush 11
     *              25 putfield #4 <com/an/object/User.age>
     *              28 return
     *
     *          String参数构造器<init>
     *              0 aload_0
     *              1 invokespecial #1 <java/lang/Object.<init>>
     *              4 aload_0
     *              5 ldc #2 <jack>
     *              7 putfield #3 <com/an/object/User.name>
     *              10 aload_0
     *              11 bipush 10
     *              13 putfield #4 <com/an/object/User.age>
     *              16 aload_0
     *              17 ldc #5 <rose>
     *              19 putfield #3 <com/an/object/User.name>
     *              22 aload_0
     *              23 aload_1
     *              24 putfield #3 <com/an/object/User.name>
     *              27 return
     *
     *          int参数构造器<init>
     *              0 aload_0
     *              1 invokespecial #1 <java/lang/Object.<init>>
     *              4 aload_0
     *              5 ldc #2 <jack>
     *              7 putfield #3 <com/an/object/User.name>
     *              10 aload_0
     *              11 bipush 10
     *              13 putfield #4 <com/an/object/User.age>
     *              16 aload_0
     *              17 ldc #5 <rose>
     *              19 putfield #3 <com/an/object/User.name>
     *              22 aload_0
     *              23 iload_1
     *              24 putfield #4 <com/an/object/User.age>
     *              27 return
     */

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
     *  【对象的内存布局】
     *              <对象头(Object Header)>
     *                      a,MarkWord(运行时元数据):
     *                          hashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳
     *                      b,类型指针
     *                          指向 方法区中该对象所属的类型;
     *
     *                      ***如果是数组,还包括 数组长度;
     *
     *              <实例数据(Instance Data)>
     *                  对象真正存储的有效信息
     *                      包括 程序自己定义的属性、从父类继承的属性
     *                  ***规则:
     *                      对象中先放 父类属性,再放 子类属性;
     *
     *              <对齐填充(padding)>
     *                  非必须,起到占位符的作用;
     *
     *              eg:
     *              public class Account {}
     *
     *              public class Customer {
     *
     *                  int id = 1001;
     *                  String name;
     *                  Account acc;
     *
     *                  {
     *                      name = "匿名客户";
     *                  }
     *
     *                  public Customer(){
     *                      acc = new Account();
     *                  }
     *              }
     *
     *
     *              Customer cust = new Customer();
     */

  

 

1
2
3
4
5
6
7
8
/**
     *  【对象访问】
     *      JVM 如何 通过栈桢中的对象引用 访问到 对象实例的?
     *          通过栈桢中 局部变量存储的引用类型的对象实例的具体内存地址;
     *
     *      访问方式:
     *          直接指针(Hotspot采用)、句柄访问
     */  

直接访问

 

 

句柄访问

 

posted on   anpeiyong  阅读(14)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2019-04-24 SpringCloud---API网关服务---Spring Cloud Zuul

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示