String s1 = “11”; 这句内存中怎么执行
首先java中的String 是通过char[] 存储的(这是基础知识了)
那么先研究一下char[] 是怎么存储的
public class CharArray {
public static void main(String[] args) {
char[] arr = new char[]{'1', '2'};
change(arr);
System.out.println(arr[0]);
while (true);
}
public static void change(char[] arr) {
arr[0] = 'A';
}
}
通过HSDB 可以 看出来,其实char[] 在底层C++ 中就是 TypeArrKlass
可以参考我的另一篇博客
Java中的类怎么在JVM(C++)中存在?类的加载过程
字符串常量池
即String Pool,但是JVM中对应的类是StringTable,底层实现是一个hashtable,看代码
class StringTable : public Hashtable<oop, mtSymbol> {
……
index 的生成方式
1、通过String的内容+长度生成hash值
2、将hash值转为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;
}
Value的生成方式
将Java的String类的实例instanceOopDesc封装成HashtableEntry
HashtableEntry 相当于java中HashMap中的Entry<Key,Value>
HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
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.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());
}
}
回到正题
String s1 = “11”;
等价于
String s1 = new String(“11”)
- 从字符串常量池中按照key=“11”;找HashtableEntry,如果找到了直接返回HashtableEntry的Value。因为HashtableEntry的Value就指向了String类的实例instanceOopDesc
- 如果没有找到,则会创建String类的实例instanceOopDesc,并将其封装到字符串常量池。
- 由于"11"最终保存在char[],所以还会创建TypeArrKlass的OopDesc,然后将这个OopDesc赋值给String的instanceOopDesc;
图解