天天看点

Java运行时数据区域解析(二)

Java运行时数据区域解析(二)

Java运行时数据区域解析(二)

Java虚拟机在Java程序执行的过程中会把其管理的内存分为若干个不同的数据区域。他们有着各自不同的特性。这些区域有的随着虚拟机进程的启动而一直存在,有的和用户线程同生共死。

Java运行时数据区域解析(二)

方法区与堆一样,是各个线程共享的,用于存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

方法区是堆的一个逻辑部分,原则上如何实现方法区属于虚拟机实现细节,不受《Java虚拟机规范》管束,不要求统一。

JDK7及之前使用永久代实现方法区,JDK8之后完全废弃了方法区e概念,改用在本地内存中实现的“元空间”来代替。

当方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。

运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译期生成的各种字面量和符号引用,这部分在类加载后存放到方法区的运行时常量池中。

一般来说,除了符号引用,由它翻译而来的直接引用也会存储在运行时常量池中。

运行时常量池相比Class文件常量池的一个重要特征是具备动态性,Java语言并不要求常量只有在编译期才能产生,也就是说并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可以将新的常量放入池中。String类的intern方法就是利用这种特性编写的。

直接内存并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。

在JDK1.4中新加入了NIO类(New Input/Output),引入了一种基于通道与缓冲区的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了Java堆和Native堆之间来回复制数据。

显然,直接内存的分配不会受到Java堆内存大小的限制。