详解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代码经典广告
Oct 21 Javascript
从零开始学习jQuery (二) 万能的选择器
Oct 01 Javascript
js动态创建上传表单通过iframe模拟Ajax实现无刷新
Feb 20 Javascript
利用函数的惰性载入提高javascript代码执行效率
May 05 Javascript
js图片处理示例代码
May 12 Javascript
微信小程序 location API接口详解及实例代码
Oct 12 Javascript
bmob js-sdk 在vue中的使用教程
Jan 21 Javascript
实例详解ztree在vue项目中使用并且带有搜索功能
Aug 24 Javascript
代码整洁之道(重构)
Oct 25 Javascript
express启用https使用小记
May 21 Javascript
详解微信小程序轨迹回放实现及遇到的坑
Feb 02 Javascript
Python机器学习之决策树和随机森林
Jul 15 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
Windows中使用计划任务自动执行PHP程序实例
2014/05/09 PHP
php获取URL中带#号等特殊符号参数的解决方法
2014/09/02 PHP
javascript事件模型实例分析
2015/01/30 Javascript
JS实现FLASH幻灯片图片切换效果的方法
2015/03/04 Javascript
删除javascript所创建子节点的方法
2015/05/21 Javascript
vue.js利用Object.defineProperty实现双向绑定
2017/03/09 Javascript
jQuery利用FormData上传文件实现批量上传
2018/12/04 jQuery
微信小程序使用map组件实现检索(定位位置)周边的POI功能示例
2019/01/23 Javascript
vuex实现购物车的增加减少移除
2020/06/28 Javascript
Python常见异常分类与处理方法
2017/06/04 Python
numpy 进行数组拼接,分别在行和列上合并的实例
2018/05/08 Python
浅谈Python里面小数点精度的控制
2018/07/16 Python
django框架实现一次性上传多个文件功能示例【批量上传】
2019/06/19 Python
使用python对多个txt文件中的数据进行筛选的方法
2019/07/10 Python
Pandas分组与排序的实现
2019/07/23 Python
Django使用Jinja2模板引擎的示例代码
2019/08/09 Python
Python IDLE或shell中切换路径的操作
2020/03/09 Python
Python数据库封装实现代码示例解析
2020/09/05 Python
利用python查看数组中的所有元素是否相同
2021/01/08 Python
一款纯css3实现的圆形旋转分享按钮旋转角度可自己调整
2014/09/02 HTML / CSS
为世界各地的女性设计和生产时尚服装:ROMWE
2016/09/17 全球购物
丝芙兰新加坡官网:Sephora新加坡
2018/12/04 全球购物
来自南加州灵感的工作和娱乐服装:TravisMathew
2019/05/01 全球购物
餐饮主管岗位职责
2013/12/10 职场文书
交通事故检查书范文
2014/01/30 职场文书
四年级数学教学反思
2014/02/02 职场文书
大学生心理活动总结
2014/07/04 职场文书
村创先争优活动总结
2014/08/28 职场文书
学校查摆问题整改措施
2014/09/28 职场文书
中学生思想品德评语
2014/12/31 职场文书
2015年公司行政后勤工作总结
2015/05/20 职场文书
优秀党员先进事迹材料2016
2016/02/29 职场文书
教你用Python写一个植物大战僵尸小游戏
2021/04/25 Python
pytorch 如何使用amp进行混合精度训练
2021/05/24 Python
如何用Laravel包含你自己的帮助函数
2021/05/27 PHP
SpringBoot深入分析讲解监听器模式下
2022/07/15 Java/Android