详解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 相关文章推荐
讲两件事:1.this指针的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件处理上的区别
Apr 12 Javascript
javascript学习笔记(十四) window对象使用介绍
Jun 20 Javascript
javascript实现的一个带下拉框功能的文本框
May 08 Javascript
推荐 21 款优秀的高性能 Node.js 开发框架
Aug 18 Javascript
理解javascript回调函数
Dec 28 Javascript
JavaScript整除运算函数ceil和floor的区别分析
Apr 14 Javascript
js实现简单的省市县三级联动效果实例
Feb 18 Javascript
JS复制对应id的内容到粘贴板(Ctrl+C效果)
Jan 23 Javascript
如何获取元素的最终background-color
Feb 06 Javascript
BootStrap自定义popover,点击区域隐藏功能的实现
Jan 23 Javascript
layui的table单击行勾选checkbox功能方法
Aug 14 Javascript
详解用场景去理解函数柯里化(入门篇)
Apr 11 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
东芝TOSHIBA RP-F11电路分析
2021/03/02 无线电
使用字符串函数输出整数化的PHP版本号
2006/10/09 PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
2013/04/23 PHP
PHP小教程之实现双向链表
2014/06/12 PHP
PHP生成不重复随机数的方法汇总
2014/11/19 PHP
PHP的Yii框架中Model模型的学习教程
2016/03/29 PHP
PHP实现类似于C语言的文件读取及解析功能
2017/09/01 PHP
PHP swoole和redis异步任务实现方法分析
2019/08/12 PHP
Laravel关系模型指定条件查询方法
2019/10/10 PHP
Laravel实现搜索的时候分页并携带参数
2019/10/15 PHP
JS面向对象编程 for Cookie
2010/09/19 Javascript
修改file按钮的默认样式实现代码
2013/04/23 Javascript
js获取IP和PcName(IE)在vs中可用
2013/08/02 Javascript
JS常用表单验证方法总结
2014/05/22 Javascript
用console.table()调试javascript
2014/09/04 Javascript
js实现向右横向滑出的二级菜单效果
2015/08/27 Javascript
JavaScript动态数量的文件上传控件
2016/11/18 Javascript
EditPlus中的正则表达式 实战(4)
2016/12/15 Javascript
js 判断数据类型的几种方法
2017/01/13 Javascript
vue代码分割的实现(codesplit)
2018/11/13 Javascript
vue elementui 实现搜索栏公共组件封装的实例代码
2020/01/20 Javascript
Vue+tracking.js 实现前端人脸检测功能
2020/04/16 Javascript
python使用PyGame绘制图像并保存为图片文件的方法
2015/04/24 Python
python获取list下标及其值的简单方法
2016/09/12 Python
python中如何使用朴素贝叶斯算法
2017/04/06 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
Python实现Mysql数据统计及numpy统计函数
2019/07/15 Python
全网最细 Python 格式化输出用法讲解(推荐)
2021/01/18 Python
纯CSS3实现移动端展开和收起效果的示例代码
2020/04/26 HTML / CSS
鲜为人知的HTML5语音合成功能
2019/05/17 HTML / CSS
安全生产投入制度
2014/01/29 职场文书
绿色环保标语
2014/06/12 职场文书
2015年社区工作总结
2015/04/08 职场文书
2015年化验员工作总结
2015/04/10 职场文书
《观察物体》教学反思
2016/02/17 职场文书
Apache Hudi的多版本清理服务彻底讲解
2022/03/31 Servers