详解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 相关文章推荐
图片之间的切换
Jun 26 Javascript
JS 遮照层实现代码
Mar 31 Javascript
Javascript new关键字的玄机 以及其它
Aug 25 Javascript
jquery中防刷IP流量软件影响统计的一点对策
Jul 10 Javascript
jQuery中(function(){})()执行顺序的理解
Mar 05 Javascript
jQuery获得包含margin的outerWidth和outerHeight的方法
Mar 25 Javascript
Jquery注册事件实现方法
May 18 Javascript
Grunt入门教程(自动任务运行器)
Aug 06 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
May 31 Javascript
vscode中vue-cli项目es-lint的配置方法
Jul 30 Javascript
JS实现字体背景跑马灯
Jan 06 Javascript
JavaScript中的LHS和RHS分析详情
Apr 06 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
数据库的日期格式转换
2006/10/09 PHP
关于PHP5 Session生命周期介绍
2010/03/02 PHP
用PHP的超级变量$_GET获取HTML表单(Form) 数据
2011/05/07 PHP
解析PHP多种序列化与反序列化的方法
2013/06/06 PHP
phpmyadmin打开很慢的解决方法
2014/04/21 PHP
HTTP头隐藏PHP版本号实现过程解析
2020/12/09 PHP
分享精心挑选的12款优秀jQuery Ajax分页插件和教程
2012/08/09 Javascript
SeaJS入门教程系列之SeaJS介绍(一)
2014/03/03 Javascript
JS+CSS实现自适应选项卡宽度的圆角滑动门效果
2015/09/15 Javascript
JavaScript如何动态创建table表格
2020/08/02 Javascript
AngularJS 使用$sce控制代码安全检查
2016/01/05 Javascript
javascript加减乘除的简单实例
2016/07/12 Javascript
微信小程序如何获取群聊的openGid以及名称详解
2019/07/17 Javascript
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
Emberjs 通过 axios 下载文件的方法
2019/09/03 Javascript
python使用webbrowser浏览指定url的方法
2015/04/04 Python
Python如何获取系统iops示例代码
2016/09/06 Python
python 获取网页编码方式实现代码
2017/03/11 Python
Python实现的文本简单可逆加密算法示例
2017/05/18 Python
Python爬虫番外篇之Cookie和Session详解
2017/12/27 Python
详解Python如何生成词云的方法
2018/06/01 Python
对Python正则匹配IP、Url、Mail的方法详解
2018/12/25 Python
Python 迭代,for...in遍历,迭代原理与应用示例
2019/10/12 Python
Python ini文件常用操作方法解析
2020/04/26 Python
基于python实现破解滑动验证码过程解析
2020/05/28 Python
基于python实现复制文件并重命名
2020/09/16 Python
Jupyter安装链接aconda实现过程图解
2020/11/02 Python
css3动画事件—webkitAnimationEnd与计时器time事件
2013/01/31 HTML / CSS
canvas绘制树形结构可视图形的实现
2020/04/03 HTML / CSS
仓库保管员岗位职责
2013/12/20 职场文书
党性观念心得体会
2014/09/03 职场文书
预备党员自我批评思想汇报
2014/10/10 职场文书
党组织领导班子整改方案
2014/10/25 职场文书
贫困证明书范文
2015/06/16 职场文书
2016干部作风整顿心得体会
2016/01/22 职场文书
教你使用vscode 搭建react-native开发环境
2021/07/07 Javascript