详解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 相关文章推荐
PHP 与 js的通信(via ajax,json)
Nov 16 Javascript
判断一个变量是数组Array类型的方法
Sep 16 Javascript
js 绑定键盘鼠标事件示例代码
Feb 12 Javascript
JavaScript 实现简单的倒计时弹窗DEMO附图
Mar 05 Javascript
jQuery中选择器小问题(新人难免遇到)
Mar 31 Javascript
JQuery表格拖动调整列宽效果(自己动手写的)
Sep 01 Javascript
JavaScript地理位置信息API
Jun 11 Javascript
防止重复发送 Ajax 请求
Feb 15 Javascript
WebStorm ES6 语法支持设置&amp;babel使用及自动编译(详解)
Sep 08 Javascript
小程序云函数调用API接口的方法
May 17 Javascript
Laravel admin实现消息提醒、播放音频功能
Jul 10 Javascript
Node.js fs模块(文件模块)创建、删除目录(文件)读取写入文件流的方法
Sep 03 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
在PHP中使用Sockets 从Usenet中获取文件
2008/01/10 PHP
通达OA公共代码 php常用检测函数
2011/12/14 PHP
百度工程师讲PHP函数的实现原理及性能分析(二)
2015/05/13 PHP
php实现复制移动文件的方法
2015/07/29 PHP
PHP实现微信发红包程序
2015/08/24 PHP
教你在header中隐藏php的版本信息
2016/08/10 PHP
PHP读取Excel类文件
2017/05/15 PHP
Javascript miscellanea -display data real time, using window.status
2007/01/09 Javascript
jquery实现的点击翻书效果代码
2015/11/04 Javascript
js倒计时抢购实例
2015/12/20 Javascript
Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面
2016/07/01 Javascript
Bootstrap基本模板的使用和理解1
2016/12/14 Javascript
JavaScript中防止微信浏览器被整体拖动的方法
2017/08/25 Javascript
vue element-ui table表格滚动加载方法
2018/03/02 Javascript
解决vue中修改export default中脚本报一大堆错的问题
2018/08/27 Javascript
Vue axios设置访问基础路径方法
2018/09/19 Javascript
详解微信小程序之scroll-view的flex布局问题
2019/01/16 Javascript
vue动态注册组件实例代码详解
2019/05/30 Javascript
通过实例解析json与jsonp原理及使用方法
2020/09/27 Javascript
ant design pro中可控的筛选和排序实例
2020/11/17 Javascript
Python脚本处理空格的方法
2016/08/08 Python
Python算法输出1-9数组形成的结果为100的所有运算式
2017/11/03 Python
Pycharm 设置默认头的图文教程
2019/01/17 Python
Python安装selenium包详细过程
2019/07/23 Python
Python中BeautifuSoup库的用法使用详解
2019/11/15 Python
python socket通信编程实现文件上传代码实例
2019/12/14 Python
Tensorflow进行多维矩阵的拆分与拼接实例
2020/02/07 Python
Python 实现一行输入多个数字(用空格隔开)
2020/04/29 Python
利用CSS3实现平移动画效果示例代码
2016/10/12 HTML / CSS
英国马莎百货官网:Marks & Spencer
2016/07/29 全球购物
美国领先的商务贺卡出版商:The Gallery Collection
2018/02/13 全球购物
服务之星获奖感言
2014/01/21 职场文书
校园摄影活动策划方案
2014/02/05 职场文书
田径运动会通讯稿
2015/07/18 职场文书
golang正则之命名分组方式
2021/04/25 Golang
Python中使用tkFileDialog实现文件选择、保存和路径选择
2022/05/20 Python