您的位置:首页 > 编程语言 > Java开发

[jvm]深入JVM(一):从"abc"=="abc"看java的连接过程

2008-02-27 15:39 573 查看
一般说来,我不关注java底层的东西,这次是一个朋友问到了,注意不光是 System.out.println("abc"=="abc");返回true, System.out.println(("a"+"b"+"c").intern()=="abc");也返回true;这和java的连接过程有关。
java解析CONSTANT_String_info时,java虚拟机必须把一个字符串对象的引用,放到constant pool entry 中。每个java虚拟机维护着一张列表,里面有所有程序被"interned"的字符串对象的引用。
查看constPoolOop.cpp文件
oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
oop entry = *(this_oop->obj_at_addr(which));
if (entry->is_symbol()) {
ObjectLocker ol(this_oop, THREAD);
if (this_oop->tag_at(which).is_unresolved_string()) {
// Intern string
symbolOop sym = this_oop->unresolved_string_at(which);
entry = StringTable::intern(sym, CHECK_(constantPoolOop(NULL)));
this_oop->string_at_put(which, entry);
} else {
// Another thread beat us and interned string, read string from constant pool
entry = this_oop->resolved_string_at(which);
}
}
assert(java_lang_String::is_instance(entry), "must be string");
return entry;
}
注意有特定字符序列的字符串只会出现一次。如果存在这个Unicode字符序列的字符串,直接返回这个字符串的引用,否则创建新的字符串对象。
查看symbolTable.cpp文件
oop StringTable::intern(Handle string_or_null, jchar* name,
int len, TRAPS) {
unsigned int hashValue = hash_string(name, len);
int index = the_table()->hash_to_index(hashValue);
oop string = the_table()->lookup(index, name, len, hashValue);

// Found
if (string != NULL) return string;

// Otherwise, add to symbol to table
return the_table()->basic_add(index, string_or_null, name, len,
hashValue, CHECK_0);
}
the_table()的定义,SymbolTable* SymbolTable::_the_table = NULL;
使用string类的intern()方法,来intern一个字符串,如果具有相同字符序列的字符串被intern过,那末intern()方法直接返回被interned字符串对象的引用。
这样的代码
public static final String a="123";
public static final String b="123";
System.out.println(a==b);

返回也是true,如果一个程序多个类使用相同的字符串,这些类的方法使用ldc或者ldc_w把内容为"123"的string对象的引用压入栈。也就是说java虚拟机把所有具有相同字符顺序的字符串处理为同一个java对象。
对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
从String源码得知这是一个native方法。
查看jdk代码
JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str))
JVMWrapper("JVM_InternString");
JvmtiVMObjectAllocEventCollector oam;
if (str == NULL) return NULL;
oop string = JNIHandles::resolve_non_null(str);
oop result = StringTable::intern(string, CHECK_0);
return (jstring) JNIHandles::make_local(env, result);
JVM_END
也调用了StringTable::intern。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐