阿里面试官:字符串在JVM中如何存放?90%的人就真的只回答在哪里存放
目录:
- 一道面试题的引出
- 案例分析
- intern 源码分析
- 总结
1. 一道面试题的引出
在面试BAT这种一线大厂时,如果面试官问道:字符串在 JVM 中如何存放?大多数人能顺利的给出如下答案:
字符串对象在JVM中可能有两个存放的位置:字符串常量池或堆内存。
- 使用常量字符串初始化的字符串对象,它的值存放在字符串常量池中;
- 使用字符串构造方法创建的字符串对象,它的值存放在堆内存中;
但是如果能针对上述回答,做进一步扩展,会给你的面试表现加分不少,让你从一大波候选人中脱颖而出。下面就一起来分析一下。
首先来看,String提供了一个API, java.lang.String.intern(),这个API可以手动将一个字符串对象的值转移到字符串常量池中
在1.7之前,字符串常量池是在PermGen区域,这个区域的大小是固定的,不能在运行时根据需要扩大,也不能被垃圾收集器回收,因此如果程序中有太多的字符串调用了intern方法的话,就可能造成OOM。
在1.7以后,字符串常量池移到了堆内存中,并且可以被垃圾收集器回收,这个改动降低了字符串常量池OOM的风险。
2. 案例分析
验证代码:
3. intern源码分析
我们来看intern方法的实现,intern方法的底层是一个native方法,在Hotspot JVM里字符串常量池它的逻辑在注释里写得很清楚:
如果常量池中有这个字符串常量,就直接返回,否则将该字符串对象的值存入常量池,再返回。
这里以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的大小是固定的,如果常量池中的字符串过多,会影响程序运行效率。
最新文章
- AutoMapper搬运工之配置
- flex进行页面的基础布局
- JQuery 快速入门一篇通
- 快速搭建VPN服务器
- App 打包并跳过 AppStore 的发布下载
- Mac工具
- Form_Form Builder Export导出为Excel(案例)
- sql中with as的用法练习
- [Angular2 Form] Display Validation and Error Messaging in Angular 2
- android菜鸟学习笔记2----关于adb
- git设置对比工具
- 转载IEnumerable与IEnumerator区别
- 【leetcode】Intersection of Two Linked Lists(easy)
- iOS-关于微信支付
- Android 使用BroadcastReceiver的几种方法
- PHP ORM笔记
- 2017 年的 人生 hard 模式终于结束了,2018年回归初心
- PHP 简单的加密解密方法
- 编译安装mysql5.7.24踩的坑
- pythonのSocket
热门文章
- Java_百钱买百鸡
- 这道面试必问的JVM面试题70%的Java程序员会做错
- srvany.exe读取配置文件问题
- LeetCode刷题总结-栈、链表、堆和队列篇
- public class 和 class的区别
- wx-icon和progress
- vue解惑之slot(插槽)
- Java 包(package)的概念及实例
- 流式计算(一)-Java8Stream
- linux,发布.netcore填坑,自动升级core版本后,运行报错:'Microsoft.AspNetCore.App', version '3.0.0' was not found.