-
Notifications
You must be signed in to change notification settings - Fork 45.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
修正一些关于字符串常量池,序列化,GC 算法的描述 #2484
Conversation
修正字符串常量池引用的描述
同步修改字符串常量池的描述
修正序列化相关的描述
修正序列化相关描述
补充,序列化相关的描述也有点问题。在序列化详解中也提到了序列化不止可以序列化为二进制字节流外的数据,但是在 简单来说 中没有提及到。 |
修正GC算法描述问题
补充 x2,JVM GC 算法的分代收集算法中的描述,应该是 “复制”(Copying) 算法,不是 “标记-复制”算法。 |
你的理解我还是有点搞不懂呀: HotSpot 虚拟机中字符串常量池的实现是 src/hotspot/share/classfile/stringTable.cpp ,StringTable 可以简单理解为一个固定大小的HashTable ,容量为 StringTableSize(可以通过 -XX:StringTableSize 参数来设置),保存的是字符串(key)和 字符串对象的引用(value)的映射关系,字符串对象的引用指向堆中的字符串对象。 字符串对象存在于堆内存中,虽然JDK1.7 字符串常量池和静态变量从永久代移动了 Java 堆中,但这样按照你的说法是不是太容易让人误解了呢? |
字节码注释: 如果字符串常量池中不存在字符串对象 “abc”,那么它首先会在字符串常量池中创建字符串对象 "abc",然后在堆内存中再创建其中一个字符串对象 "abc"。 示例代码(JDK 1.8): String s1 = new String("abc"); 对应的字节码: // 在堆内存中分配一个尚未初始化的 String 对象。
// #2 是常量池中的一个符号引用,指向 java/lang/String 类。
// 在类加载的解析阶段,这个符号引用会被解析成直接引用,即指向实际的 java/lang/String 类。
0 new #2 <java/lang/String>
// 复制栈顶的 String 对象引用,为后续的构造函数调用做准备。
// 此时操作数栈中有两个相同的对象引用:一个用于传递给构造函数,另一个用于保持对新对象的引用,后续将其存储到局部变量表。
3 dup
// JVM 先检查字符串常量池中是否存在 "abc"。
// 如果常量池中已存在 "abc",则直接返回该字符串的引用;
// 如果常量池中不存在 "abc",则 JVM 会在常量池中创建该字符串字面量并返回它的引用。
// 这个引用被压入操作数栈,用作构造函数的参数。
4 ldc #3 <abc>
// 调用构造方法,使用从常量池中加载的 "abc" 初始化堆中的 String 对象
6 invokespecial #4 <java/lang/String.<init> : (Ljava/lang/String;)V>
// 将堆中的 String 对象引用存储到局部变量表
9 astore_1
// 返回,结束方法
10 return
|
感谢完善,我提交了一个新版本:7cf404b |
嗯嗯,我是基于仓库内容产生疑问并进行推断的,有一些理解不到位的情况,感谢 Guide 哥的贡献。 |
这块确实容易有误解,我也有疏忽和理解不到位的地方,不好意思呀!持续完善! |
原文中的描述可以概况为 字符串常量池中保存了引用,但是字符串常量池位于堆内存中,保存的是对象而不是引用,引用位于栈内存中。因此我修改了两篇 md 文档中对于字符串常量池的描述,并且对 ldc 指令描述进行了修改。
另外,原文的图片中的描述也有问题。但是我无法修改图片的文字,因为图片是使用 oss 图床的。