jvm内存模型

一.jvm内存模型

jvm的内存模型分配如下:
1.程序计数器
用来记录线程当前的执行的字节码行数,不会产生OOM异常
2.虚拟机栈(线程栈)
每个线程都对应一个栈,栈中为线程的每个方法分配一个栈帧,栈帧中包含局部变量表、操作数栈、动态链接、方法出口等信息。
局部变量表:存储方法中的局部变量(包括基本类型和引用类型)
操作数栈:一个用于计算的临时数据存储区(当要运算时,将数据出栈,放到cpu寄存器中运算)
动态链接:在运行期间,将方法区里面的符号引用转为直接引用(即:给出地址)
方法出口:当前方法执行完,返回到哪个位置
StackOverflowError
造成原因:vm规定了栈的最大深度,当执行时栈的深度大于了规定的深度。如不当递归操作,死循环等。
解决方案:
(1)检查程序,看是否有死循环
(2)通过 JVM 启动参数 -Xss 增加线程栈内存空间, 某些正常使用场景需要执行大量方法或包含大量局部变量,这时可以适当地提高线程栈空间限制,例如通过配置 -Xss2m 将线程栈空间调整为 2 mb。
3.
所有线程共享的一块内存区域,在虚拟机启动时创建。所有创建的对象和数组都存放在堆上。空间分为新生代和老年代。新生代又分为eden区(伊甸园),Survivor1和Survivor2区。
OutOfMemoryError: Java heap space:堆内存溢出
造成原因:在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满
解决方案:
(1)检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。
(2) 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m
4.方法区(在1.8中为元空间)
用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用
OutOfMemoryError: Metaspace
造成原因:加载到内存中的 class 数量太多或者体积太大
解决方案:
(1)-XX:MaxMetaspaceSize=512m
这里将 Metaspace 的最大值设置为 512MB, 如果没有用完, 就不会抛出 OutOfMemoryError。
(2)有一种看起来很简单的方案, 是直接去掉 Metaspace 的大小限制。 但需要注意, 不限制Metaspace内存的大小, 假若物理内存不足, 有可能会引起内存交换(swapping), 严重拖累系统性能。 此外,还可能造成native内存分配失败等问题。

MetaspaceSize默认为21M,如果达到该值会造成full gc,同时收集器会对该值进行调整:如果释放了大量的空间,适当降低;如果释放的空间很少,那么在不超过-XX:MaxMetaspaceSize的情况下,适当提高该值。如果启动时经常发生full gc,有可能是元空间或者方法区发生了大小调整。所以尽量吧metaspace和MaxMetaspaceSize设置成一样的值,并设置的比初始值大一些。

你可能感兴趣的:(java,jvm)