Java教程

jvm内存结构

本文主要是介绍jvm内存结构,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

jdk1.8

JVM 内存共分为虚拟机栈、堆、元数据区、程序计数器、本地方法栈五个部分。

程序计数器:线程私有,它可以看做是当前线程所执行 的字节码的行号指示器。不会发生异常

虚拟机栈:线程私有,用于存储栈帧。每个方法执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等。

        局部变量表:是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量(8种基本类型、对象引用和returnAddress类型)

         操作数栈:是一个后入先出栈(LIFO)。随着方法执行和字节码指令的执行,会从局部 变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者 返回给方法调用者,也就是出栈/入栈操作

        动态链接:Java虚拟机栈中,每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,持有这个引用的目的是为了 支持方法调用过程中的动态链接(将符号引用转换成直接引用)

        方法返回地址:程序正常退出或异常退出,都需要返回到方法被调用的位置,程序才能继续进行

本地方法栈:线程私有,与虚拟机栈所发挥的作用是非常相似的, 其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码) 服务, 而本地方法栈则是为虚拟机使用到的本地(Native) 方法服务

堆:jvm共享,Java堆(Java Heap) 是虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java世界里“几乎”所有的对象实例都在这里分配内存,jdk1.8后静态变量和常量池等并入堆中。

元空间:存储类的元信息。最大可利用空间是整个系统内存的可用空间。

Java堆溢出

public class HeapOOM {
    static class OOMObject {
    }
    public static void main(String[] args) {
        List<OOMObject> oomObjectList = new ArrayList<>();
        while (true) {
            oomObjectList.add(new OOMObject());
        }
} }

说明:不断向oomObjectList添加对象导致GC Roots 到对象之间有可达路径来避免垃圾收集回收机制清除这些对象。新生代满后,会发生Minor GC,GC完成后空间仍不足,将对象放入老年代,老年代空间不足会发生Full GC,之后如果空间还不足以存放新对象则抛 出 OutOfMemoryError 异常。

原因:

        内存中加载数据过多

        集合对对象引用过多且使用完后未清除

        代码存在死循环产生过多重复对象

        堆分配不合理

虚拟机栈和本地方法栈溢出

如果线程请求栈最大深度超过虚拟机所允许的最大深度,会抛出StackOverflowError异常。

如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。

 

这篇关于jvm内存结构的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!