详解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 相关文章推荐
jquery实现表格奇数偶数行不同样式(有图为证及实现代码)
Jan 23 Javascript
jQuery数据缓存功能的实现思路及简单模拟
May 27 Javascript
javascript通过获取html标签属性class实现多选项卡的方法
Jul 27 Javascript
JS模态窗口返回值兼容问题的完美解决方法
May 28 Javascript
第六篇Bootstrap表格样式介绍
Jun 21 Javascript
Bootstrap入门教程一Hello Bootstrap初识
Mar 02 Javascript
ng2学习笔记之bootstrap中的component使用教程
Mar 09 Javascript
AngularJS service之select下拉菜单效果
Jul 28 Javascript
详解React Native网络请求fetch简单封装
Aug 10 Javascript
Vue2.0学习之详解Vue 组件及父子组件通信
Dec 12 Javascript
vue微信分享的实现(在当前页面分享其他页面)
Apr 16 Javascript
JavaScript手写数组的常用函数总结
Nov 22 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/03/15 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
ThinkPHP3.2框架操作Redis的方法分析
2019/05/05 PHP
js利用div背景,做一个竖线的效果。
2008/11/22 Javascript
Prototype Number对象 学习
2009/07/19 Javascript
jQuery第三课 修改元素属性及内容的代码
2010/03/14 Javascript
jquery 字符串切割函数substring的用法说明
2014/02/11 Javascript
jQuery制作的别致导航有阴影背景高亮模式窗口
2014/04/15 Javascript
node.js中的console.time方法使用说明
2014/12/09 Javascript
微信小程序 闭包写法详细介绍
2016/12/14 Javascript
js用类封装pop弹窗组件
2017/10/08 Javascript
Vue精简版风格概述
2018/01/30 Javascript
微信小程序中时间戳和日期的相互转换问题
2018/07/09 Javascript
在Vue项目中取消ESLint代码检测的步骤讲解
2019/01/27 Javascript
通过实例解析JavaScript for in及for of区别
2020/06/15 Javascript
javascript实现前端成语点击验证优化
2020/06/24 Javascript
JS遍历树层级关系实现原理解析
2020/08/31 Javascript
python实现倒计时的示例
2014/02/14 Python
Python中的urllib模块使用详解
2015/07/07 Python
Python对象转JSON字符串的方法
2016/04/27 Python
解决python2.7用pip安装包时出现错误的问题
2017/01/23 Python
Python类的动态修改的实例方法
2017/03/24 Python
基于python的Tkinter编写登陆注册界面
2017/06/30 Python
下载python中Crypto库报错:ModuleNotFoundError: No module named ‘Crypto’的解决
2018/04/23 Python
Django框架多表查询实例分析
2018/07/04 Python
对Python闭包与延迟绑定的方法详解
2019/01/07 Python
python使用SQLAlchemy操作MySQL
2020/01/02 Python
使用python采集Excel表中某一格数据
2020/05/14 Python
利用PyQt5+Matplotlib 绘制静态/动态图的实现代码
2020/07/13 Python
button在IE6/7下的黑边去除方案
2012/12/24 HTML / CSS
美国专业消费电子及摄影器材网站:B&H Photo Video
2019/12/18 全球购物
bonprix荷兰网上商店:便宜的服装、鞋子和家居用品
2020/07/04 全球购物
美术毕业生求职信
2014/02/25 职场文书
Python列表删除重复元素与图像相似度判断及删除实例代码
2021/05/07 Python
Python中递归以及递归遍历目录详解
2021/10/24 Python
HttpClient实现表单提交上传文件
2022/08/14 Java/Android