详解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函数代码
Apr 17 Javascript
jquery+html仿翻页相册功能
Dec 20 Javascript
jQuery实现两列等高并自适应高度
Dec 22 Javascript
VUE JS 使用组件实现双向绑定的示例代码
Jan 10 Javascript
node.js中grunt和gulp的区别详解
Jul 17 Javascript
Vue2.0 组件传值通讯的示例代码
Aug 01 Javascript
图片懒加载imgLazyLoading.js使用详解
Sep 15 Javascript
Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)
May 04 Javascript
微信小程序使用canvas的画图操作示例
Jan 18 Javascript
微信小程序实现点击空白隐藏的方法示例
Aug 13 Javascript
详解Webpack4多页应用打包方案
Jul 16 Javascript
js制作提示框插件
Dec 24 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
与空气斗智斗勇的经典《Overlord》,传说中的“无稽之谈”
2020/04/09 日漫
php生成RSS订阅的方法
2015/02/13 PHP
php curl 获取https请求的2种方法
2015/04/27 PHP
Laravel框架实现文件上传的方法分析
2019/09/29 PHP
Alliance vs AM BO3 第二场2.13
2021/03/10 DOTA
解决jquery中美元符号命名冲突问题
2014/01/08 Javascript
Nodejs关于gzip/deflate压缩详解
2015/03/04 NodeJs
jQuery实现ajax调用WCF服务的方法(附带demo下载)
2015/12/04 Javascript
跨域资源共享 CORS 详解
2016/04/26 Javascript
动态更新highcharts数据的实现方法
2016/05/28 Javascript
Javascript 制作图形验证码实例详解
2016/12/22 Javascript
Angular.js去除页面中显示的空行方法示例
2017/03/30 Javascript
Vue.js实现在下拉列表区域外点击即可关闭下拉列表的功能(自定义下拉列表)
2017/05/30 Javascript
js实现canvas保存图片为png格式并下载到本地的方法
2017/08/31 Javascript
jQuery实现的事件绑定功能基本示例
2017/10/11 jQuery
微信小程序 如何引入外部字体库iconfont的图标
2018/01/31 Javascript
vue-cli3 karma单元测试的实现
2019/01/18 Javascript
javascript实现切割轮播效果
2019/11/28 Javascript
用js编写留言板
2020/03/17 Javascript
[03:28]2014DOTA2国际邀请赛 EG战队官方纪录片
2014/07/21 DOTA
python操作数据库之sqlite3打开数据库、删除、修改示例
2014/03/13 Python
PyTorch上实现卷积神经网络CNN的方法
2018/04/28 Python
Selenium鼠标与键盘事件常用操作方法示例
2018/08/13 Python
Pytorch 多维数组运算过程的索引处理方式
2019/12/27 Python
python实现同一局域网下传输图片
2020/03/20 Python
django的autoreload机制实现
2020/06/03 Python
浅谈keras中loss与val_loss的关系
2020/06/22 Python
django美化后台django-suit的安装配置操作
2020/07/12 Python
Roxy俄罗斯官方网站:冲浪和滑雪板的一切
2020/06/20 全球购物
什么是Deployment descriptors;都有什么类型的部署描述符
2015/07/28 面试题
英语系本科生求职信范文
2013/12/18 职场文书
城市轨道交通工程职业生涯规划书范文
2014/09/16 职场文书
接收函
2019/04/22 职场文书
php引用传递
2021/04/01 PHP
详解Html5项目适配系统深色模式方案总结
2021/04/14 HTML / CSS
深入解析Apache Hudi内核文件标记机制
2022/03/31 Servers