详解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 相关文章推荐
JavaScript 核心参考教程 内置对象
Oct 13 Javascript
网页中CDATA标记的说明
Sep 12 Javascript
扩展jquery实现客户端表格的分页、排序功能代码
Mar 16 Javascript
jquery判断RadioButtonList和RadioButton中是否有选中项示例
Sep 29 Javascript
jQuery之选项卡的简单实现
Feb 28 Javascript
浅谈jQuery中的checkbox问题
Aug 10 Javascript
浅谈js原生拖放
Nov 21 Javascript
JavaScript浏览器对象模型BOM(BrowserObjectModel)实例详解
Nov 29 Javascript
Bootstrap中datetimepicker使用小结
Dec 28 Javascript
微信小程序收货地址API兼容低版本解决方法
May 18 Javascript
js实现页面多个日期时间倒计时效果
Jun 20 Javascript
vue中的面包屑导航组件实例代码
Jul 01 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 文件上传进度条的两种实现方法的代码
2007/11/25 PHP
编写安全 PHP应用程序的七个习惯深入分析
2013/06/08 PHP
PHP如何通过AJAX方式实现登录功能
2015/11/23 PHP
原生PHP实现导出csv格式Excel文件的方法示例【附源码下载】
2019/03/07 PHP
Yii Framework框架使用PHPExcel组件的方法示例
2019/07/24 PHP
在laravel中使用with实现动态添加where条件
2019/10/10 PHP
jQuery过滤选择器:not()方法使用介绍
2014/04/20 Javascript
js delete 用法(删除对象属性及变量)
2014/08/24 Javascript
JS中完美兼容各大浏览器的scrolltop方法
2015/04/17 Javascript
JavaScript中的Math.SQRT1_2属性使用简介
2015/06/14 Javascript
JS+CSS实现的竖向简洁折叠菜单效果代码
2015/10/22 Javascript
JavaScript关于提高网站性能的几点建议(一)
2016/07/24 Javascript
jQuery实用小技巧_输入框文字获取和失去焦点的简单实例
2016/08/25 Javascript
利用JQuery阻止事件冒泡
2016/12/01 Javascript
无阻塞加载js,防止因js加载不了影响页面显示的问题
2016/12/18 Javascript
jQuery分页插件jquery.pagination.js使用方法解析
2017/02/09 Javascript
在JavaScript中如何访问暂未存在的嵌套对象
2019/06/18 Javascript
jQuery实现简单聊天室
2020/02/08 jQuery
js防抖函数和节流函数使用场景和实现区别示例分析
2020/04/11 Javascript
Node.js API详解之 net模块实例分析
2020/05/18 Javascript
JavaScript undefined及null区别实例解析
2020/07/21 Javascript
JS如何生成动态列表
2020/09/22 Javascript
在Vue中使用Select选择器拼接label的操作
2020/10/22 Javascript
python实现汉诺塔方法汇总
2016/07/25 Python
Python实现矩阵转置的方法分析
2017/11/24 Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
2019/06/04 Python
详解Python中namedtuple的使用
2020/04/27 Python
python实现数据结构中双向循环链表操作的示例
2020/10/09 Python
python中scipy.stats产生随机数实例讲解
2021/02/19 Python
我的applet原先好好的, 一放到web server就会有问题,为什么?
2016/05/10 面试题
文明班级建设方案
2014/05/15 职场文书
网络技术专业求职信
2014/07/13 职场文书
2014老师三严三实对照检查材料思想汇报
2014/09/18 职场文书
八年级历史教学反思
2016/02/19 职场文书
Python文件的操作示例的详细讲解
2021/04/08 Python
Redis数据结构之链表与字典的使用
2021/05/11 Redis