APP下载

JAVA面试官:请说什么是字串常量池?

消息来源:baojiabao.com 作者: 发布时间:2024-05-21

报价宝综合消息JAVA面试官:请说什么是字串常量池?

Java设计者为String提供了字串常量池以提高其效能,那么字串常量池的具体原理是什么,我们需要带着以下三个问题,去理解字串常量池:

字串常量池的设计意图是什么?字串常量池在哪里?如何操作字串常量池?字串常量池的设计意图是什么?

字串的分配,和其他的物件分配一样,耗费高昂的时间与空间代价。

JVM为了提高效能和减少内存开销,在例项化字串常量的时候进行了一些优化:

为了减少在JVM中建立的字串的数量,字串类维护了一个字串池,每当程式码建立字串常量时,JVM会首先检查字串常量池;

如果字串已经存在池中,就返回池中的例项引用;

如果字串不在池中,就会例项化一个字串并放到池中。Java能够进行这样的优化是因为字串是不可变的,可以不用担心资料冲突进行共享;

实现的基础:

因为字串是不可变的,可以不用担心资料冲突进行共享;

执行时例项建立的全域性字串常量池中有一个表,总是为池中每个唯一的字串物件维护一个引用,这就意味着它们一直引用着字串常量池中的物件,所以,在常量池中的这些字串不会被垃圾收集器回收。

我们来看下面一段程式码,就是从字串常量池中获取相应的字串:

字串常量池在哪里?

在分析字串常量池的位置时,首先得了解JVM内存模型,JVM内存区域分为执行绪共享区执行绪独占区

执行绪共享区包括 [堆] 和 [方法区]

执行绪独占区包括 [Java虚拟机器栈]、[本地方法栈] 和 [陈程式计数器]

方法区:

存放载入的类资讯、常量、静态变数,静态程式码块等资讯;

类资讯包括类的版本、字段、方法、界面等,方法区也被称为永久代。

程式计数器:

是一块比较小的内存区域,是唯一一个不会发生OutOfMemoryError的区域,可以这样理解方法进栈后,每一行程式码都有一个标识,程式按著标识往下执行。

Java虚拟机器栈:

每个方法执行,都会建立一个栈帧,方法呼叫进栈,方法结束出栈; 栈帧里面存放着区域性变量表,算子栈,动态连结以及方法出口等;

区域性变量表里面存放着基本资料型别,引用型别等; 栈帧伴随着方法的开始而开始,结束而结束;

区域性变量表所需的内存空间在编译期间就完成了分配,在执行期间是不会改变的;

栈很容易出现StackOverFlowError,栈内存溢位错误,常见于递回呼叫;

本地方法栈和Java虚拟机器栈:

其实是差不多的,但是也是有区别的Java虚拟机器栈为Java方法服务,本地方法栈为native方法服务

堆:

功能单一,就是储存物件的例项,堆其实又分新生代和老年代;

新生代又分Eden、Survivor01和Survivor02三个区域,垃圾收集器主要管理的区域,Eden区回收效率很高。

并不是所有的物件例项都会分配到堆上去,Java虚拟机器栈也会分配。堆很容易出现OutOfMemoryError错误,内存溢位

如何操作字串常量池?

JVM例项化字串常量池时

String.intern()判断这个常量是否存在于常量池。

如果存在{

判断存在内容是引用还是常量{

如果是引用{

返回引用地址指向堆空间物件

}

如果是常量{

直接返回常量池常量

}

}

}

如果不存在{

将当前物件引用复制到常量池,并且返回的是当前物件的引用

}

通过new操作符建立的字串物件不指向字串池中的任何物件,但是可以通过使用字串的intern()方法来指向其中的某一个。java.lang.String.intern()返回一个保留池字串,就是一个在全域性字串池中有了一个入口。如果以前没有在全域性字串池中,那么它就会被新增到里面。

2019-10-29 06:55:00

相关文章