详解JVM系列之内存模型


Posted in Javascript onJune 10, 2021

1. 内存模型和运行时数据区

这一章学习java虚拟机内存模型(Java Virtual machine menory model),可以这样理解,jvm运行时数据库是一种规范,而JVM内存模型是对改规范的实现

详解JVM系列之内存模型

java虚拟机重点存储数据的是堆和方法区,所以本章节也重点从这两个方面进行比较详细描述。堆和方法区是内存共享的,而java虚拟机栈、Native方法栈、程序计数器是线程私有的

详解JVM系列之内存模型

2、思维导图和图例

详解JVM系列之内存模型

一个是非堆区(方法区),方法区也一般被称之为“永久代”。另外一个是堆区,分为young区和old区,young区又分为两个部分,一个是Eden区,一个是Survivor区(S0+S1),S0区也可以称之From区,S1也可以称之为To区

详解JVM系列之内存模型

3、对象向JVM申请空间

详解JVM系列之内存模型

4、为什么需要Survivor区?

为什么需要Survivor区?只有Eden不行吗?

假设不设计出Survivor区,Eden区进行一次MinorGC,对象就直接被送到Old区,这样一来Old区很快就被填满,Old区一满,就会进行FullGC(Old区会进行MajorGC,一般伴随着MinorGC),FullGC是很耗时的,所以设计出Survivor区的目的是减少对象被送到Old区,有一个过渡的Survivor区

补充:Minor GC:新生代
Major GC:老年代
Full GC:新生代+老年代
Eden:S1:S2是8:1:1

5、为什么需要两个Survivor区?

需要两个Survivor区的目的是为了避免内存碎片化。为什么这么说?
假设只设计出一个Survivor区,一旦Eden区满了,就会进行Minor GC,Eden区存活的对象就会被移动到Survivor区,等下一次Eden区满时候,问题就来了,进行MinorGC就将Eden区对象硬放到Survivor区,这样就导致了对象所占的内存是不连续的

6、例子进行验证

堆内存溢出

import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class HeapController {

    List<Foo> list = new ArrayList<Foo>();
    @GetMapping(value = {"heap"})
    public String heapTest() {
        while (true) {
            list.add(new Foo());
        }
    }


    @Data
    class Foo {
        String str;
    }
}

访问接口,出现内存溢出;

java.lang.OutOfMemoryError: Java heap space

...

可以设置参数:比如-Xms64M -Xmx512M

方法区内存溢出

使用asm,maven配置:

<dependency>
  <groupId>asm</groupId>
  <artifactId>asm</artifactId>
  <version>3.3.1</version>
</dependency>

编写代码,向方法区中添加Class的信息,注意,电脑性能不够好,不要执行此代码,很容易,造成电脑重启,太吃内存,也可以调小循环次数

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.util.ArrayList;
import java.util.List;

public class MyMetaspace extends ClassLoader {

  public static List<Class<?>> createClasses() {
    List<Class<?>> classes = new ArrayList<Class<?>>();
    for (int i = 0; i < 10000000; ++i) {
      ClassWriter cw = new ClassWriter(0);
      cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,
              "java/lang/Object", null);
      MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
              "()V", null, null);
      mw.visitVarInsn(Opcodes.ALOAD, 0);
      mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
              "<init>", "()V");
      mw.visitInsn(Opcodes.RETURN);
      mw.visitMaxs(1, 1);
      mw.visitEnd();
      MyMetaspace test = new MyMetaspace();
      byte[] code = cw.toByteArray();
      Class<?> exampleClass = test.defineClass("Class" + i, code, 0,
              code.length);
      classes.add(exampleClass);
    }
    return classes;
  }
}

方法区测试接口:

import com.example.jvm.jvmexceptionexample.asm.MyMetaspace;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class NonHeapController {

    List<Class<?>> list = new ArrayList<Class<?>>();

    @GetMapping(value = {"/noheap"})
    public String noheap() {
        while (true) {
            list.addAll(MyMetaspace.createClasses());
        }
    }

}

java.lang.OutOfMemoryError: Metaspace

at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.5_54]

处理方法,设置Metaspace的大小,比如-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=512M

Java虚拟机栈

在前面学习,java虚拟机栈是通过栈帧方式存储,一个方法对应一个栈帧,按照队列模式进栈,所以要测试程序导致java虚拟机栈出现问题,可以通过递归方法方式进行测试:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StackController {

    public static long count = 0;

    public static void add(long i) {
        count ++ ;
        add(i);
    }

    @GetMapping(value = {"stack"})
    public void stack() {
        add(1);
    }

}

StackOverflow,栈溢出异常:

java.lang.StackOverflowError: null

at com.example.jvm.jvmexceptionexample.controller.StackController.add(StackController.java:14) ~[classes/:na]

处理方法,设置-Xss256k:设置每个线程的堆栈大小。JDK 5以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K

以上就是详解JVM系列之内存模型的详细内容,更多关于JVM 内存模型 内存结构的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
js parsefloat parseint 转换函数
Jan 21 Javascript
高亮显示web页表格行的javascript代码
Nov 19 Javascript
JS 操作符整理[推荐收藏]
Nov 15 Javascript
jquery动态改变form属性提交表单
Jun 03 Javascript
javascript实现label标签跳出循环操作
Mar 06 Javascript
JavaScript Math 对象常用方法总结
Apr 28 Javascript
js中获取jsp表单中radio类型的值简单实例
Aug 15 Javascript
jq实现左滑显示删除按钮,点击删除实现删除数据功能(推荐)
Aug 23 Javascript
JS封装通过className获取元素的函数示例
Dec 20 Javascript
微信小程序教程系列之视图层的条件渲染(10)
Apr 19 Javascript
改变layer confirm弹窗按钮的颜色方法
Sep 12 Javascript
vuex分模块后,实现获取state的值
Jul 26 Javascript
使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)
一文搞懂redux在react中的初步用法
Jun 09 #Javascript
深入详解JS函数的柯里化
Jun 09 #Javascript
javascript canvas实现雨滴效果
用JS实现飞机大战小游戏
Jun 09 #Javascript
原生JS实现飞机大战小游戏
解决Vue+SpringBoot+Shiro跨域问题
Jun 09 #Vue.js
You might like
Linux下PHP连接Oracle数据库
2014/08/20 PHP
php中Socket创建与监听实现方法
2015/01/05 PHP
php实现比较全的数据库操作类
2015/06/18 PHP
PHP+jQuery实现滚屏无刷新动态加载数据功能详解
2017/05/04 PHP
Laravel 实现密码重置功能
2018/02/23 PHP
php+ajax 文件上传代码实例
2019/03/18 PHP
php array_chunk()函数用法与注意事项
2019/07/12 PHP
用javascript实现改变TEXTAREA滚动条和按钮的颜色,以及怎样让滚动条变得扁平
2007/04/20 Javascript
JQUERY操作JSON实例代码
2010/02/09 Javascript
JavaScript闭包实例讲解
2014/04/22 Javascript
关于JavaScript命名空间的一些心得
2014/06/07 Javascript
jQuery+ajax实现鼠标单击修改内容的思路
2014/06/29 Javascript
jquery弹出遮掩层效果【附实例代码】
2016/04/28 Javascript
ichart.js绘制虚线、平均分虚线效果的实现代码
2016/05/05 Javascript
ECMAScript6快速入手攻略
2016/07/18 Javascript
angular框架实现全选与单选chekbox的自定义
2017/07/06 Javascript
vue 实现全选全不选的示例代码
2018/03/29 Javascript
javascript将非数值转换为数值
2018/09/13 Javascript
详解Vue.js在页面加载时执行某个方法
2018/11/20 Javascript
百度小程序自定义通用toast组件
2019/07/17 Javascript
python自定义异常实例详解
2017/07/11 Python
Pyinstaller 打包exe教程及问题解决
2019/08/16 Python
使用Python爬虫库requests发送请求、传递URL参数、定制headers
2020/01/25 Python
python利用xlsxwriter模块 操作 Excel
2020/10/14 Python
python 检测图片是否有马赛克
2020/12/01 Python
css3新增颜色表示方式分享
2014/04/15 HTML / CSS
澳大利亚天然护肤品、化妆品和健康产品一站式商店:Nourished Life
2018/12/02 全球购物
党委书记岗位职责
2013/11/24 职场文书
医学专业毕业生个人求职信
2013/12/25 职场文书
关于热爱祖国的演讲稿
2014/05/04 职场文书
小学运动会班级口号
2014/06/09 职场文书
2014财务年度工作总结
2014/11/11 职场文书
2015年电厂工作总结范文
2015/05/13 职场文书
哪类餐饮行业,最适合在高校创业?
2019/08/19 职场文书
祝福语集锦:送给闺蜜的生日祝福语
2019/10/08 职场文书
SpringBoot集成Redis的思路详解
2021/10/16 Redis