简介
本文介绍Java的运行时数据区域。
示意图
各区域的数据
以JDK8为例:
- 堆:对象实例、String常量池、基本类型常量池、静态变量。
- 方法区(元空间):类信息、类常量池、运行时常量池。
- 虚拟机栈:临时变量(方法内的变量)
方法区、永久代和元空间的区别
方法区是《Java 虚拟机规范》规定的一个抽象的概念。永久代和元空间是方法区的两种实现方式。
JDK8之前:用永久代作为方法区的实现,占用JVM的空间,通过Full GC进行垃圾回收(回收效率很低)。
JDK8开始:用元空间作为方法区的实现,使用本地内存,不占用JVM的空间。元空间有自己的垃圾回收机制。
JDK8为什么要调整方法区的位置?
永久代通过Full GC进行垃圾回收,回收效率很低。
永久代有JVM 设置的固定大小上限,无法进行调整。而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。元空间里面存放的是类的元数据,这样加载的元数据就不由 MaxPermSize 控制了, 而由系统的实际可用空间控制,这样能加载的类就更多了。
元空间溢出时会得到如下错误:java.lang.OutOfMemoryError: MetaSpace
相关参数:
- -XX:MaxMetaspaceSize。最大元空间大小,默认值为 unlimited,表示只受系统内存的限制。
- -XX:MetaspaceSize 元空间的初始大小,如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。
请先
!