面试官:字符串对象在JVM中是如何存放的
典型答案
字符串对象在JVM中可能有两个存放的位置:字符串常量池或者堆内存。
使用常量字符串初始化的字符串对象,它的值存放在字符串常量池中;
使用字符串构造方法创立的字符串对象,它的值存放在堆内存中;
String提供了一个API——java.lang.String.intern()
,这个API可以手动将一个字符串对象的值转移到字符串常量池中。
在1.7之前,字符串常量池是在PermGen区域,这个区域的大小是固定的——不能在运行时根据需要扩大,也不能被垃圾收集器回收,因而假如程序中有太多的字符串调用了intern方法的话,即可能造成OOM。
在1.7以后,字符串常量池移到了堆内存中,并且可以被垃圾收集器回收,这个改动降低了字符串常量池OOM的风险。
知识点总结
案例分析
验证代码:
public class StringTest { public static void main(String[] args) { 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 }}
intern源码分析
intern方法的实现底层是一个native方法,在Hotspot JVM里字符串常量池它的逻辑在注释里写得很清楚:假如常量池中有这个字符串常量,就直接返回,否则将该字符串对象的值存入常量池,再返回。
这里以Openjdk1.8的源码为例,跟下intern方法的底层实现,String.java文件对应的C文件是String.c:
JNIEXPORT jobject JNICALLJava_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的大小是固定的,假如常量池中的字符串过多,那么就会导致每个entry上的元素过多,从而影响程序效率,导致YGC的STW时间变长
读者分享
觉得不错的朋友可以点点左下角的拇指小赞一下,同时在这给大家分享少量免费的架构资料(包括 视频,课件,面试专题,学习笔记等)关注官方微信公众号,那里每天都会有技术干货、技术动向、职业生涯、行业热点、职场趣事等一切有关于程序员的内容分享。更有海量Java架构、移动互联网架构相关源码视频,面试资料,电子书籍截止于4月28日免费发放。学习资源丰富实用,有需要的朋友可以来关注,扫描下方二维码关注wx公众号免费获取↓↓↓
资源大本营↓↓↓
Java架构资料
Java源码解析,到各种框架学习,再到项目实战,一应俱全,包括但不限于:Spring、Mybatis等源码、Java进阶、Java架构师、虚拟机、性能优化、并发编程、数据结构和算法。
移动互联网架构资料
Android进阶、Android架构、APP开发、NDK板块开发、小程序开发、微信开发。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 面试官:字符串对象在JVM中是如何存放的