详解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学习笔记 更改jQuery对象
Sep 19 Javascript
简单时间提示DEMO从0开始一直进行计时
Nov 19 Javascript
jQuery实现异步获取json数据的2种方式
Aug 29 Javascript
javascript自动生成包含数字与字符的随机字符串
Feb 09 Javascript
js实现简单的可切换选项卡效果
Apr 10 Javascript
js创建数组的简单方法
Jul 27 Javascript
angular.extend方法的具体使用
Sep 14 Javascript
JS基于正则表达式实现的密码强度验证功能示例
Sep 21 Javascript
vue-cli项目中怎么使用mock数据
Sep 27 Javascript
Vue.js组件实现选项卡以及切换特效
Jul 24 Javascript
解决Vue + Echarts 使用markLine标线(precision精度问题)
Jul 20 Javascript
Js类的构建与继承案例详解
Sep 15 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
德生PL550的电路分析
2021/03/02 无线电
解析PHP中如何将数组变量写入文件
2013/06/06 PHP
PHP strip_tags()去除HTML、XML以及PHP的标签介绍
2014/02/18 PHP
php 表单提交大量数据发生丢失的解决方法
2014/03/03 PHP
CodeIgniter框架中_remap()使用方法2例
2014/03/10 PHP
php代码架构的八点注意事项
2016/01/25 PHP
PHP中SESSION过期设置
2021/03/09 PHP
JS去除字符串的空格增强版(可以去除中间的空格)
2009/08/26 Javascript
由JavaScript技术实现的web小游戏(不含网游)
2010/06/12 Javascript
JavaScript实现网页加载进度条代码超简单
2015/09/21 Javascript
详解基于Bootstrap+angular的一个豆瓣电影app
2017/06/26 Javascript
判断滚动条滑到底部触发事件(实例讲解)
2017/11/15 Javascript
基于vue中解决v-for使用报红并出现警告的问题
2018/03/03 Javascript
Angular父组件调用子组件的方法
2018/04/02 Javascript
原生js基于canvas实现一个简单的前端截图工具代码实例
2019/09/10 Javascript
Python使用Srapy框架爬虫模拟登陆并抓取知乎内容
2016/07/02 Python
Python中异常重试的解决方案详解
2017/05/05 Python
Python操作Redis之设置key的过期时间实例代码
2018/01/25 Python
django限制匿名用户访问及重定向的方法实例
2018/02/07 Python
使用Python搭建虚拟环境的配置方法
2018/02/28 Python
python中的常量和变量代码详解
2018/07/25 Python
详解python 利用echarts画地图(热力图)(世界地图,省市地图,区县地图)
2019/08/06 Python
python super的使用方法及实例详解
2019/09/25 Python
python数据库开发之MongoDB安装及Python3操作MongoDB数据库详细方法与实例
2020/03/18 Python
python中复数的共轭复数知识点总结
2020/12/06 Python
HTML5通过navigator.mediaDevices.getUserMedia调用手机摄像头问题
2020/04/27 HTML / CSS
日本乐天德国站:Rakuten.de
2019/05/16 全球购物
社会实践自我鉴定
2013/11/07 职场文书
高级电工工作职责
2013/11/21 职场文书
信访工作者先进事迹
2014/01/17 职场文书
大学生全国两会报告感想
2014/03/17 职场文书
委托公证书
2014/04/08 职场文书
2016教师学习教育法心得体会
2016/01/19 职场文书
MySQL8.0.18配置多主一从
2021/06/21 MySQL
项目中Nginx多级代理是如何获取客户端的真实IP地址
2022/05/30 Servers
HTML5之高度塌陷问题的解决
2022/06/01 HTML / CSS