常问面试:String 对象在 JVM 如何存储提高性能的?

Posted 程序员泥瓦匠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常问面试:String 对象在 JVM 如何存储提高性能的?相关的知识,希望对你有一定的参考价值。

点击蓝色“泥瓦匠BYSocket”,关注我哟 加个星标”,不忘签到哦

博览群书,修身养性,广交名士,静观天下之变” 



来源:adujava

典型答案


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

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

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

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

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

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

知识点总结


2
案例分析

常问面试:String 对象在 JVM 如何存储提高性能的?

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里字符串常量池它的逻辑在注释里写得很清楚:如果常量池中有这个字符串常量,就直接返回,否则将该字符串对象的值存入常量池,再返回。

常问面试:String 对象在 JVM 如何存储提高性能的?

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

JNIEXPORT jobject JNICALL
Java_java_lang_String_intern(JNIEnv *envjobject this)
{
   return JVM_InternString(envthis);
}

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

JVM_ENTRY(jstringJVM_InternString(JNIEnv *envjstring str))
 JVMWrapper("JVM_InternString");
 JvmtiVMObjectAllocEventCollector oam;
 if (str == NULLreturn NULL;
 oop string = JNIHandles::resolve_non_null(str);
 oop result = StringTable::intern(stringCHECK_NULL);
 return (jstringJNIHandles::make_local(envresult);
JVM_END

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

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

总结


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

以下专题教程也许您会有兴趣

  • 《程序兵法:算法与数据结构》 https://www.bysocket.com/archives/2314/algorithm

  • 《Spring Boot 2.x 系列教程》 https://www.bysocket.com/springboot

  • 《Java 核心系列教程》 https://www.bysocket.com/archives/2100

由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

-The End-

号外:为读者持续几份最新教程,覆盖了 Spring Boot、Spring Cloud、微服务架构等。


获取方式:回复 java 或 666 领取 Spring 等最新教程 

获取方式:回复 webflux 或 888领取《Spring Boot 2 WebFlux 教程》


热门文章:



i. 



长按二维码,扫扫关注哦

关注即可得 Spring Boot Cloud、微服务等干货


泥瓦匠的星球免费体验卡

我的介绍

如果文章对你有帮助的话

转发一下在看

以上是关于常问面试:String 对象在 JVM 如何存储提高性能的?的主要内容,如果未能解决你的问题,请参考以下文章

19年BAT常问面试题汇总:JVM+微服务+多线程+锁+高并发性能

Java面试时,面试官常问的问题

面试常问点:深入剖析JVM的那些事

(转)大厂常问到的14个Java面试题

面试官常问的垃圾回收器,这次全搞懂

面试官常问系列:Java虚拟机内存四大问题,都在这了!