62

字符串对象在 JVM 中是如何存放的

 5 years ago
source link: https://mp.weixin.qq.com/s/JdgkZUyeyaIdtsiKlxz3wg?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文阅读时间4分钟。

典型答案

字符串对象在JVM中可能有两个存放的位置:字符串常量池或堆内存。

  • 使用常量字符串初始化的字符串对象,它的值存放在字符串常量池中

  • 使用字符串构造方法创建的字符串对象,它的值存放在堆内存中

String提供了一个API—— java.lang.String.intern() ,这个API可以手动将一个字符串对象的值转移到字符串常量池中。

在1.7之前,字符串常量池是在 PermGen区域 ,这个区域的大小是固定的——不能在运行时根据需要扩大,也不能被垃圾收集器回收,因此如果程序中有太多的字符串调用了intern方法的话,就可能造成OOM。

在1.7以后,字符串常量池移到了堆内存中,并且可以被垃圾收集器回收,这个改动降低了字符串常量池OOM的风险。

知识点总结

2

案例分析

QFnqamV.png!web

String s1 = "javaadu";
String s2 = "javaadu";
String s3 = new String("javaadu");
        
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false

String s4 = s3.intern();
System.out.println(s1 == s4); //true

2

intern源码分析

intern方法的实现底层是一个native方法,在Hotspot JVM里字符串常量池它的逻辑在注释里写得很清楚:如果常量池中有这个字符串常量,就直接返回,否则将该字符串对象的值存入常量池,再返回。

qMjaQzV.jpg!web

这里以openjdk 1.8的源码为例,跟下intern方法的底层实现,String.java文件对应的C文件是String.c:

JNIEXPORT jobject JNICALL
Java_java_lang_String_intern(JNIEnv *env, jobject this)
{
    return JVM_InternString(env, this);
}

JVM_InternString这个方法的定义在jvm.h,实现在jvm.cpp中,在JVM中,Java世界和C++世界的连接层就是jvm.h和jvm.cpp这两文件。

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_NULL);
  return (jstring) JNIHandles::make_local(env, result);
JVM_END

可以看出,字符串常量池在JVM内部就是一个HashTable,也就是上面代码中的StringTable。

根据 StringTable::intern 方法跟下去,就可以跟到下面这段代码中,如果找到了就直接返回found_string,如果没有找到,就将当前的字符串加入到HashTable中,然后再返回。

总结

在Java应用恰当得使用String.intern()方法有助于节省内存空间,但是在使用的时候,也需要注意,因为StringTable的大小是固定的,如果常量池中的字符串过多,会影响程序运行效率。

你再主动一点点    我们就有故事了


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK