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

目錄:java

  1. 一道面試題的引出
  2. 案例分析
  3. intern 源碼分析
  4. 總結

1. 一道面試題的引出面試

在面試BAT這種一線大廠時,若是面試官問道:字符串在 JVM 中如何存放?大多數人能順利的給出以下答案:app

 

字符串對象在JVM中可能有兩個存放的位置:字符串常量池或堆內存。jvm

  • 使用常量字符串初始化的字符串對象,它的值存放在字符串常量池中;
  • 使用字符串構造方法建立的字符串對象,它的值存放在堆內存中;

 

可是若是能針對上述回答,作進一步擴展,會給你的面試表現加分很多,讓你從一大波候選人中脫穎而出。下面就一塊兒來分析一下。源碼分析

首先來看,String提供了一個API, java.lang.String.intern(),這個API能夠手動將一個字符串對象的值轉移到字符串常量池中對象

在1.7以前,字符串常量池是在PermGen區域,這個區域的大小是固定的,不能在運行時根據須要擴大,也不能被垃圾收集器回收,所以若是程序中有太多的字符串調用了intern方法的話,就可能形成OOM。blog

在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的大小是固定的,若是常量池中的字符串過多,會影響程序運行效率。

相關文章
相關標籤/搜索