详解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淡入淡出效果的实现思路
Mar 31 Javascript
extjs 分页使用jsp传递数据示例
Jul 29 Javascript
json字符串之间的相互转换示例代码
Aug 21 Javascript
sails框架的学习指南
Dec 22 Javascript
JavaScript统计字符串中每个字符出现次数完整实例
Jan 28 Javascript
BootStrap网页中代码显示用法详解
Oct 21 Javascript
微信小程序 检查接口状态实例详解
Jun 23 Javascript
JS实现快递单打印功能【推荐】
Jun 21 Javascript
Vue导出页面为PDF格式的实现思路
Jul 31 Javascript
微信打开网址添加在浏览器中打开提示的办法
May 20 Javascript
JS扁平化输出数组的2种方法解析
Sep 17 Javascript
Vue常用的全选/反选的示例代码
Feb 19 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
德生S2000电路分析
2021/03/02 无线电
写一段简单的PHP建立文件夹代码
2015/01/06 PHP
PHP使用file_get_content设置头信息的方法
2016/02/14 PHP
php数据访问之查询关键字
2016/05/09 PHP
php 替换文章中的图片路径,下载图片到本地服务器的方法
2018/02/06 PHP
HTML5如何适配 iPhone IOS 底部黑条
2021/03/09 HTML / CSS
XMLHTTPRequest的属性和方法简介
2010/11/23 Javascript
Tab页界面 用jQuery及Ajax技术实现(php后台)
2011/10/12 Javascript
jQuery代码优化之基本事件
2011/11/01 Javascript
用js判断页面刷新或关闭的方法(onbeforeunload与onunload事件)
2012/06/22 Javascript
ExtJS实现文件下载的方法实例
2013/11/09 Javascript
jQuery获得IE版本不准确webbrowser的解决方法
2014/02/23 Javascript
js 获取页面高度和宽度兼容 ie firefox chrome等
2014/05/14 Javascript
jQuery中odd选择器的定义和用法
2014/12/23 Javascript
JavaScript实现点击自动选择TextArea文本的方法
2015/07/02 Javascript
Eclipse引入jquery报错如何解决
2015/12/01 Javascript
运用js教你轻松制作html音乐播放器
2020/04/17 Javascript
Vue异步组件使用详解
2017/04/08 Javascript
vue+element实现表单校验功能
2019/05/20 Javascript
微信小程序入口场景的问题集合与相关解决方法
2019/06/26 Javascript
layui输入框中只允许输入整数的实现方法
2019/09/18 Javascript
微信小程序 多行文本显示...+显示更多按钮和收起更多按钮功能
2019/09/26 Javascript
深入理解NumPy简明教程---数组3(组合)
2016/12/17 Python
TensorFlow实现Batch Normalization
2018/03/08 Python
Python解决pip install时出现的Could not fetch URL问题
2019/08/01 Python
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
2019/08/31 Python
python 中的paramiko模块简介及安装过程
2020/02/29 Python
实现ECharts双Y轴左右刻度线一致的例子
2020/05/16 Python
音频处理 windows10下python三方库librosa安装教程
2020/06/20 Python
CSS Grid布局教程之网格单元格布局
2014/12/30 HTML / CSS
浅谈HTML5 &amp; CSS3的新交互特性
2016/07/19 HTML / CSS
eDreams巴西:廉价机票,酒店优惠和度假套餐
2017/04/14 全球购物
应届生.NET方向面试题
2015/05/23 面试题
机电专业大学生职业规划书范文
2014/02/25 职场文书
商场促销活动总结
2014/07/10 职场文书
如何理解Vue简单状态管理之store模式
2021/05/15 Vue.js