详解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 操作Javascript对象和数组的工具函数小结
Jan 22 Javascript
ExtJS GridPanel 根据条件改变字体颜色
Mar 08 Javascript
JavaScript实现复制功能各浏览器支持情况实测
Jul 18 Javascript
Javascript实现页面跳转的几种方式分享
Oct 26 Javascript
用正则表达式替换图片地址img标签
Nov 22 Javascript
jquery遍历checkbox介绍
Feb 21 Javascript
JavaScript实现带标题的图片轮播特效
May 20 Javascript
jQuery删除节点用法示例(remove方法)
Sep 08 Javascript
Javascript 判断两个IP是否在同一网段实例代码
Nov 28 Javascript
解决Angular4项目部署到服务器上刷新404的问题
Aug 31 Javascript
vue中组件的过渡动画及实现代码
Nov 21 Javascript
JS面向对象之多选框实现
Jan 17 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
ADODB类使用
2006/11/25 PHP
PHP实现将HTML5中Canvas图像保存到服务器的方法
2014/11/28 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
学习php设计模式 php实现观察者模式(Observer)
2015/12/09 PHP
JS左右无缝滚动(一般方法+面向对象方法)
2012/08/17 Javascript
jQuery实现为图片添加镜头放大效果的方法
2015/06/25 Javascript
js判断当前页面在移动设备还是在PC端中打开
2016/01/06 Javascript
jQuery过滤特殊字符及JS字符串转为数字
2016/05/26 Javascript
Angular2学习笔记——详解路由器模型(Router)
2016/12/02 Javascript
jquery滚动条插件slimScroll使用方法
2017/02/09 Javascript
AngularJS读取JSON及XML文件的方法示例
2017/05/25 Javascript
使用express+multer实现node中的图片上传功能
2018/02/02 Javascript
vue项目中使用scss的方法步骤
2019/05/16 Javascript
vue-router 中 meta的用法详解
2019/11/01 Javascript
Vue vm.$attrs使用场景详解
2020/03/08 Javascript
记一次vue跨域的解决
2020/10/21 Javascript
JavaScript对象访问器Getter及Setter原理解析
2020/12/08 Javascript
[03:00]2014DOTA2国际邀请赛 Titan淘汰潸然泪下Ohaiyo专访
2014/07/15 DOTA
Python编写百度贴吧的简单爬虫
2015/04/02 Python
python 接口实现 供第三方调用的例子
2019/08/13 Python
基于pytorch 预训练的词向量用法详解
2020/01/06 Python
tensorflow多维张量计算实例
2020/02/11 Python
Python 随机生成测试数据的模块:faker基本使用方法详解
2020/04/09 Python
css3背景图片透明叠加属性cross-fade简介及用法实例
2013/01/08 HTML / CSS
英国电信商店:BT Shop
2019/12/17 全球购物
JPA的特点
2014/10/25 面试题
网上卖盒饭创业计划书范文
2014/02/07 职场文书
小学生学习感言
2014/03/10 职场文书
历史专业大学生职业生涯规划书
2014/03/13 职场文书
教师年度个人总结
2015/02/11 职场文书
2015秋季小学开学寄语
2015/05/27 职场文书
本科毕业论文答辩稿
2015/06/23 职场文书
医生行业员工的辞职信
2019/06/24 职场文书
人为什么会“幸灾乐祸”?
2019/08/06 职场文书
python套接字socket通信
2022/04/01 Python
python单向链表实例详解
2022/05/25 Python