干了两晚,带你探索那讲不清的字符串
常量池(后期专门找一篇说一下)
1、class文件中
通过命令:javap -verbose XXX
Constant pool:#1 = Methodref #23.#50 // java/lang/Object."<init>":()V#2 = Methodref #22.#51 // com/luban/ziya/string/TestIntern.test5:()V#3 = String #52 // 1
....
在硬盘上
2、运行时常量池
一般说的常量池就是指这儿
InstanceKlass的一个属性
ConstantPool* _constants;
方法区(元空间)
3、字符串常量池
即String Pool,但是JVM中对应的类是StringTable,底层实现是一个hashtable,看代码
class StringTable : public Hashtable<oop, mtSymbol> {
……
在堆区
Hashtable是如何存储字符串的
例如 name = “aaa”,sex = “man”,zhiye = “teacher”
假设 name进行hashValue后是 11,sex的hashValue = 13,zhiye的hashValue = 11,
存储方式可以参考下图
根据key从hashtable中查数据
1、将key通过hash算法计算成hashValue(name:11)
2、根据11去hashtable中去找,如果index=11关联的元素只有一个,直接返回
3、如果是多个,根据链表进行遍历,比对key
java中的字符串在jvm中是如何存储的
StringTable的Key的生成
1、根据字符串以及字符串的长度计算出hashValue
2、根据hashValue计算出index,这个index就是key
hashValue = hash_string(name, len);
index = hash_to_index(hashValue);// Pick hashing algorithm
unsigned int StringTable::hash_string(const jchar* s, int len) {return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :java_lang_String::hash_code(s, len);
}// Bucket handling
int hash_to_index(unsigned int full_hash) {int h = full_hash % _table_size;assert(h >= 0 && h < _table_size, "Illegal hash value");return h;
}
StringTable的Value的生成
将Java的String类的实例instanceOopDesc(String类在JVM中的存在形式)封装成HashtableEntry(就是一个结构体)
struct HashtableEntry {INT_PTR hash;void* key; //hashValuevoid* value; //instanceOopDescHashtableEntry* //next;};
HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string()); // 这里的string()指的就是instanceOopDesc
add_entry(index, entry);template <class T, MEMFLAGS F> HashtableEntry<T, F>* Hashtable<T, F>::new_entry(unsigned int hashValue, T obj) {HashtableEntry<T, F>* entry;entry = (HashtableEntry<T, F>*)BasicHashtable<F>::new_entry(hashValue);entry->set_literal(obj);return entry;
}
**String有时候会存储到StringTable,有的时候不会,**后面会有StringBuffer的案例,可以看到对象的值直接就是,而不是指向常量池,这个与与intern还有渊源,
下面是周志明大佬书中的一段内容(这本书强烈建议Java开发者读一下 这本书强烈建议Java开发者读一下 这本书强烈建议Java开发者读一下)
String.hashcode()
String类重写了hashcode方法
public int hashCode() {int h = this.hash;if (h == 0 && this.value.length > 0) {char[] val = this.value;for(int i = 0; i < this.value.length; ++i) {h = 31 * h + val[i];}this.hash = h;}return h;
}
可以看出String的hashcode与String的内容是有关系的,因此下面的代码的hashcode是相等的
public class TestHashcode {public static void main(String[] args) {String s1 = "11";String s2 = new String("11");System.out.println(s1.hashCode());System.out.println(s2.hashCode());}
}
不同方式创建字符串在JVM中的存在形式
String 是用一个字符数组来存储值的,基本类型的数组的元信息存放在TypeArrayKlass中,它的对象是存在TypeArrayOopDesc中。
private final char value[];
字符数组在JVM中是怎样存在的
运行以下代码,通过HSDB查看
public class CharArray {public static void main(String[] args) {char[] arr = new char[]{'1', '2'};while (true);}
}
可以看到元信息是存储在TypeArrayKlass中
一个双引号
以下代码生成了几个oop
String s1 = "1";
生成两个oop 一个String
1、TypeArrayOopDesc char数组
2、InstanceOopDesc String对象
证明
debug以下代码
此时内存中的char[] 和String的数量如下图
当执行完第20行后,结果如下图,可以看到二者均 +1
接下来图解一下,以以下代码为例
public static void test1() {String s1 = "11";
}
两个双引号
以下代码生成了几个oop
String s1 = "2";
String s2 = "2";
此时你是不是想说三个
继续debug以下代码
执行完24行时
执行完25行时
可以发现增加了两个
• 推酷-技术 点击" 技术领导力 "关注 ∆ 每天 早上8:30 推送 来阿里两年多了,从 1 个人,到现在带领 50 多人的团队,走过了一段艰辛的充满变化的带团队历程,在这 ... 点击"技术领导力"关注∆ 每天早上8:30推送 来阿里两年多了,从 1 个人,到现在带领 50 多人的团队,走过了一段艰辛的充满变化的带团队历程,在这里总结下自己过去两年带 15 ... 带你探索条形码世界的奥秘 序 二维码也就是QR码受所谓的移动互联网吵得也比较火,但是同学我奉劝你还是把一维的先搞懂吧.首先要说的就是印在商品上的条形码 就仅仅是一串竖条而已没什么玄机,对印刷面也无特定 ... 10分钟带你探索css中更为奇妙的奥秘 题目描述 三角形面积=SQRT(S*(S-a)*(S-b)*(S-c)) 其中S=(a+b+c)/2,a.b.c为三角形的三边. 定义两个带参的宏,一个用来求area, 另一个宏用来求S. 写程序,在 ... .Net Discovery系列文章是讲述.Net平台机制的文章,目前已有12篇,分别讲述了.Net垃圾收集.实时编译.字符串等部件的机制,现在推出1周年之际总结文章阅读索引,希望对大家有所帮助. ... 背景图为:网易Bgwan/Lofter&&:click 写在前面 很久没有更新内容了,本篇准备介绍一些基础实用性的内容,-字符串处理之正则表达式 字符串是编程时涉及到的最多的一种数据结 ... 题目要求: 编写一个C程序,实现以下功能:编写一个常规的函数和一个递归函数,两个函数均能将输入的一个字符串以按反序形式的字符串作为返回值.在main函数中输入一行字符串,分别调用两个函数,输出反序后的 ... 1.创建两个长度为10的数组,数组内元素为随机生成的.不重复的 1-100之间的整数. 2.定义一个方法,传入两个数组,方法中将两个数组不同的元素拼接成一个字符串,并且将该字符串以及字符串的长度输出到 ...干了两晚,带你探索那讲不清的字符串相关推荐
最新文章
热门文章