转载

阿里面试官:字符串在JVM中如何存放?90%的人就真的只回答在哪里存放

点击上方 石杉的架构笔记 ,右上角选择“ 设为星标

每日早8点半,技术文章准时送上

公众号后台回复“ 学习 ”,获取作者独家秘制精品资料

往期文章

BAT 面试官是如何360°无死角考察候选人的(上篇)

每秒上万并发下的Spring Cloud参数优化实战

分布式事务如何保障实际生产中99.99%高可用

记一位朋友斩获 BAT 技术专家Offer的面试经历

亿级流量架构系列之如何支撑百亿级数据的存储与计算

本文来源:javaadu

目录:

  1. 一道面试题的引出

  2. 案例分析

  3. intern 源码分析

  4. 总结

1. 一道面试题的引出

在面试BAT这种一线大厂时,如果面试官问道:字符串在 JVM 中如何存放?大多数人能顺利的给出如下答案:

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

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

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

但是如果能针对上述回答,做进一步扩展,会给你的面试表现加分不少,让你从一大波候选人中脱颖而出。下面就一起来分析一下。

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

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

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

2. 案例分析

阿里面试官:字符串在JVM中如何存放?90%的人就真的只回答在哪里存放

验证代码:

3. intern源码分析

我们来看intern方法的实现,intern方法的底层是一个native方法,在Hotspot JVM里字符串常量池它的逻辑在注释里写得很清楚:

如果常量池中有这个字符串常量,就直接返回,否则将该字符串对象的值存入常量池,再返回。

阿里面试官:字符串在JVM中如何存放?90%的人就真的只回答在哪里存放

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

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

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

StringTable::intern 方法跟下去,可以发现:如果找到了这次操作的字符串,就直接返回found_string;如果没有找到,就将当前的字符串加入到HashTable中,然后再返回。

4. 总结

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

END

划至底部,点击“ 在看 ”,是你来过的仪式感!

推荐阅读:

  • 简历写了会Kafka,面试官90%会让你讲讲acks参数对消息持久化的影响!

  • 面试最让你手足无措的一个问题:你的系统如何支撑高并发?

  • Java高阶必备:如何优化Spring Cloud微服务注册中心架构?

  • 高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

  • 从团队自研的百万并发中间件系统的内核设计看Java并发性能优化!

  • 如果20万用户同时访问一个热点缓存,如何优化你的缓冲架构?

更多文章:

  • 2018年原创汇总

  • 2019年原创汇总(持续更新)

  • 爆款推荐

  • 面试专栏

欢迎长按下图关注公众号 石杉的架构笔记 ,后台回复“ 学习 ”,获取作者独家秘制精品资料

阿里面试官:字符串在JVM中如何存放?90%的人就真的只回答在哪里存放

BAT架构经验倾囊相授

阿里面试官:字符串在JVM中如何存放?90%的人就真的只回答在哪里存放

原文  http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247485377&idx=1&sn=5f8ca42d133b304c16afee2eebfc5028
正文到此结束
Loading...