前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JVM(五)

JVM(五)

作者头像
小土豆Yuki
发布2021-09-02 10:08:58
2470
发布2021-09-02 10:08:58
举报
文章被收录于专栏:洁癖是一只狗洁癖是一只狗

什么是内存溢出,那些区域会发生内存溢出

首先我们要知道java是如何运行一个JVM进程,如下代码

代码语言:javascript
复制
public class Demo3 {
public static void main(String[] args) {
        String message = "hello world";
        System.out.println(message);
    }
}
  1. 首先是写好的代码编译成class文件
  1. 执行java命令
  1. jVM加载你写的类
  1. main线程执行方法
  1. 局部变量进入虚拟机栈
  1. 堆内存创建对象

如上几步,能发生OOM地方

  • metaspace区域用来存放类的信息,如果加载的类信息太多就可能导致OOM
  • 每个线程都有个虚拟机栈,就是所谓的栈内存,这里存放的是方法的里面的局部变量,栈内存大小一般是1m,不断的循环调用方法,就可能导致OOM
  • 堆内存,放一些对象,不断的创建对象,也是可能发生OOM

Metaspace如何触发内存溢出呢

我们用下面参数设置Metaspace内存大小

代码语言:javascript
复制
-XX:MetaspaceSize=512m
-XX:MaxMetaspaceSize=512m

固定512M,当Metaspace满了之后,就会触发FULL GC,回收的条件也比较苛刻,如这个类加载器被回收,这个类的所有对象实例都被回收等等,所以一旦Metaspace满了,未必会回收里面的很多类,一旦回收之后,还是有很多存活的类,如果继续想Metaspace加入更多的类信息,就会导致OOM

导致Metaspace的一般原因如下

  • Metaspace的值太小,只有几十MB,(一般系统512MB)当对于一个稍微大型的系统,由于他有许多的类信心,就可能导致Metaspace不够用
  • 有很多系统用cgLIB之类的技术动态生成一些类,一旦代码没有控制住,就会创建过多的类,容易把Metaspace给塞满,进而引发内存溢出

虚拟机栈溢出

我们知道一个线程的虚拟机栈的内存大小是固定的,一般默认是1MB,正如我们之前讲的main()方法,就会产生一个main的栈帧,如下代码

代码语言:javascript
复制
public class Demo3 {
public static void main(String[] args) {
        String message = "hello world";
        System.out.println(message);
        sayHello("我是肉丝");
    }    
public static  void sayHello(String name){
        System.out.println("你好,杰克"+name);
    }
}

每一个方法的调用,都会在虚拟机栈中创建一个栈帧,保存对应的局部变量,但是此时我们要注意的是每一个帧栈也是要占内存的,虽然一些变量和其他的对象数据占不了太大的内存,但是实际上也是要占用的,

如果一个线程不断的调用各种方法,不停的把方法的栈帧压入虚拟机栈,就会不断的占用这个线程1MB的栈内存,最终会导致栈内存溢出

什么情况下会发生栈内存溢出呢

代码语言:javascript
复制
public static  void sayHello(String name){
        sayHello(name);
    }

如上代码,出现这种不断递归调用,就有可能导致栈内存溢出,一般来说不会导致栈内存溢出,除非你的bug才会导致

堆内存溢出

  1. 首先平时我们系统不断创建对象,然后大量的对象进入Eden区,一旦Eden区满之后,就会发生一次YGC,然后存活对象进入S区
  1. 一旦高并发场景,ygc后很多请求还没有处理完毕,存活对象很多,S区,放不下,就会进入老年代
  1. 一旦老年代满了,就会发生FULL gc
  1. 不幸的是老年代GC之后,还是有很多对象存活,此时年轻代不断不断GC,把存活的对象转移到老年代,但是老年代也空间不足了

最终就会由于堆内存实在放不下对象,导致内存溢出,JVM崩溃

一般什么场景会导致堆内存溢出呢

  • 系统承载高并发,因为请求量过大,导致大量对象存活,所以要继续放入新的对象实在不行了,就会引起OOM
  • 系统内存泄露,就莫名其妙弄很多对象,结果对象都是存活的,没有及时取消他的引用,就会导致GC无法回收,引发内存泄漏最终OOM
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档