详解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 11 Javascript
JavaScript 匿名函数(anonymous function)与闭包(closure)
Oct 04 Javascript
javascript将数组插入到另一个数组中的代码
Jan 10 Javascript
javascript 实现 秒杀,团购 倒计时展示的记录 分享
Jul 12 Javascript
深入理解Javascript动态方法调用与参数修改的问题
Dec 10 Javascript
javascript数据类型示例分享
Jan 19 Javascript
探索Vue.js component内容实现
Nov 03 Javascript
Vue指令的钩子函数使用方法
Mar 20 Javascript
微信小程序实战之登录页面制作(5)
Mar 30 Javascript
jQuery Json数据格式排版高亮插件json-viewer.js使用方法详解
Jun 12 jQuery
JavaScript数据类型的存储方法详解
Aug 25 Javascript
[原创]jquery判断元素内容是否为空的方法
May 04 jQuery
使用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下MAIL的另一解决方案
2006/10/09 PHP
PHP form 表单传参明细研究
2009/07/17 PHP
PHP 函数学习简单小结
2010/07/08 PHP
Javascript技术技巧大全(五)
2007/01/22 Javascript
event对象的方法 兼容多浏览器
2009/06/27 Javascript
jquery 模板的应用示例
2013/11/12 Javascript
jQuery选择器之基本选择器与层次选择器
2015/03/03 Javascript
js实现的鼠标滚轮滚动切换页面效果(类似360默认页面滚动切换效果)
2016/01/27 Javascript
浅析AngularJS中的指令
2016/03/20 Javascript
全面解析多种Bootstrap图片轮播效果
2016/05/27 Javascript
json对象与数组以及转换成js对象的简单实现方法
2016/06/24 Javascript
AngularJs自定义服务之实现签名和加密
2016/08/02 Javascript
对javascript继承的理解
2016/10/11 Javascript
ES6下React组件的写法示例代码
2017/05/04 Javascript
js获取图片的base64编码并压缩
2020/12/05 Javascript
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
Python递归函数实例讲解
2019/02/27 Python
教你一步步利用python实现贪吃蛇游戏
2019/06/27 Python
Mac在python3环境下安装virtualwrapper遇到的问题及解决方法
2019/07/09 Python
python logging模块书写日志以及日志分割详解
2019/07/22 Python
详解Python3 中的字符串格式化语法
2020/01/15 Python
Python confluent kafka客户端配置kerberos认证流程详解
2020/10/12 Python
Python3使用 GitLab API 进行批量合并分支
2020/10/15 Python
浅析Python 中的 WSGI 接口和 WSGI 服务的运行
2020/12/09 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
2021/01/29 Python
CSS中垂直居中的简单实现方法
2015/07/06 HTML / CSS
英国水族馆和池塘用品购物网站:Warehouse Aquatics
2019/08/29 全球购物
阿里巴巴的Oracle DBA笔试题答案-SQL tuning类
2016/04/03 面试题
初中科学教学反思
2014/01/21 职场文书
个人授权委托书范本
2014/04/03 职场文书
合作协议书格式
2014/08/19 职场文书
思想工作总结范文
2015/08/12 职场文书
2016年党员创先争优公开承诺书
2016/03/25 职场文书
django上传文件的三种方式
2021/04/29 Python
【海涛解说】pis亲自推荐,其实你从来不会玩NW
2022/04/01 DOTA