无用的对象回收和内存管理无需关心,JVM已经做好了
1.运行时数据区域:方法区,堆,虚拟机栈,本地方法栈,程序计数器
*程序计数器:线程私有的,可以看成是当前线程执行的字节码的指示器,字节码解释器工作时就是通过改变计数器来选取下一条需要执行的字节码指令.唯一一个
没有规定任何OOM异常的区域(知识点:OOM-out of memory 内存溢出)
*虚拟机栈:线程私有的,生命周期于线程相同,栈里面存储的是方法的局部变量、对象的引用等.
这块区域规定了两种异常:1.当线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverFlowError
2.当虚拟机栈动态扩展无法申请到足够的内存时抛出OOM
*本地方法栈:线程私有的,和虚拟机栈作用相同,只不过是为本地方法(Native)服务的,HotSpot虚拟机直接将虚拟机栈和本地方法栈合并了
*堆:线程共享的,虚拟机管理的内存最大的一块,在虚拟机创建时创建.唯一作用就是存放对象实例,就是new出来的对象.也是jvm垃圾回收器主要工作区域
*方法区:线程共享,存放虚拟机加载的类信息、常量、静态变量.也被称为永久代.当方法区无法满足内存分配时,抛出OOM
除此之外,还有运行常量池和直接内存
*运行时常量池属于方法区的一部分,用于存放编译器生成的各种字面量和符号引用.抛出OOM
*直接内存不属于虚拟机运行时数据区的一部分,也不是虚拟机的内存区域,但是NIO会直接使用,受本地总内存的限制,抛出OOM
JAVA 8 中的改变:
对于方法区,也成为永久代,用于存储类的信息、常量池、方法数据、方法代码.
java.lang.OutMemoryError.PermGenspace异常,PermGenspace就是指方法区.
在JDK 1.8中,HotSpot虚拟机已经没有方法区了,取而代之的是Metaspace(元空间),原空间不在虚拟机中,而是使用本地内存,在默认情况下,元空间只受本地内存限制
好处:1.字符串常量存放在方法区中,容易出现性能问题和内存溢出
2.类和方法的信息难以确定大小,因此方法区的大小难以指定,太小容易内存溢出,太大容易导致堆空间不足
2.方法区的垃圾回收会带来不必要的复杂度,并且回收效率低