内存结构

方法区

JDK1.7 之前包含1.7 将方法区称为 Perm Space 永久代

JDK1.8之后包含1.8 将方法区称为 MetaSpace 元空间。

堆(分配内存会大一些)

分配对象、new 实例。

堆内存当中划分为两个区域:老年代和新生代。

如何去划分老年代和新生代,根据对象的年龄。这个年龄是一个对象经过一次GC,如果还存在的话,年龄就加一。当年龄超过默认值(15)时,就会从新生代划分到老年代当中。

1.新生代(Young)

  1. new Object() ,实例化10个单位为1的对象 ===>>> 新生代分配
  2. 新生代内存不够用时,触发GC
  3. GC之后,释放空间,会存在空间碎片
  4. 这时又new一个对象,这时这个对象的单位是3;GC之后释放的空间不连续,导致新生代不够分配,又会再一次触GC
  5. GC的弊端就是会消耗线程资源,stop the world。

以上的设计显然是不合理的,重新设计之后

新生代new出来的对象是朝生夕死,将新生代划分为两个区域:Eden区,Survivor区。Survivor区又划分为S0、S1两个区域;

新生代内存分配情况是:Eden区80%,Survivor区20%(S0:10%,S1:10%)。

如果刚new出来的对象太大,超过了新生代的Eden区内存,会直接存入在老年代。

举例说明:

老年代:2G内存

新生代:1G内存

Eden区800MB

S0,S1各100MB

这是new一个900MB的对象,会直接分配在老年代(Old)里。

新生代(Young)GC:Minor GC

老年代(Old)GC:Major GC

  • Eden区

所有刚刚new出来的对象,就会分配在Eden区。

  • Survivor区
  1. S0、S1永远有一块内存是浪费的,一块被使用;

  2. S0、S1两个区域互相转换身份,以空间的浪费换取内存空间的连续性;

  3. Eden=80%;S0=10%;S1=10%;Eden:S0:S1=8:1:1;

  4. 比如说直接new一个900MB的新对象,会直接在老年代(Old)区进行分配;

  5. 如果新生代(Young)区的Young GC之后对象的年龄不断的+1+1+1 > 年龄15之后,会将该对象存放到老年代(Old)区;

    假如这时新生代(Young)区有120MB存活对象,S区不够放了,会跟老年代借20MB的空间存放,会触发担保机制,这20MB依旧还是属于老年代(Old)管理的。

  6. 极端情况,如果有个对象超过老年代内存直接OOM。

2.老年代(Old)

如果老年代的内存不够用了,会触发 Old GC 也可 称为 Major GC。Old GC会比较耗时。当然一旦触发了Old GC(Major GC)通常都会伴随着Young GC(Minor GC)

Old GC(Major GC)+ Young GC(Minor GC)+ MetaSpace GC(可以忽略它)= Full GC

调优的原则:

避免触发Full GC,换句话说避免触发Old GC(Major GC);如果要触发GC,尽量只触发Young GC(Minor GC)。

  1. 尽量减少GC次数
  2. 尽量只触发Young GC(Minor GC)

实操:

在IDEA中VM options设置JVM堆内存:-Xms30M -Xmx30M(设置堆内存30MB,最大30MB)

@RestController
@RequestMapping("/test/jvm")
public class TestJvmController {
List<AuthAccount> list = new ArrayList<>();
@GetMapping("/jvmTest")
public void jvmTest() {
while (true) {
list.add(new AuthAccount());
}
}
}

运行SpringBoot程序后、在JAVA安装目录中,找到bin文件夹下的jvisualvm工具(这个工具是JDK自带的),首先还要安装Visual GC的插件才能查看到JVM GC运行时状况

之后等待程序运行后,打开这个jvisualvm工具就可以查看到JVM内存运行时的状况

如果堆内存中,没有可分配的内存空间了,就会报OOM。

同理方法区Metaspace也会报OOM,设置JVM中方法区大小:-XX:MetaspaceSize=40M -XX:MaxMetaspaceSize=40M。

栈也会报OOM,首先我们先测试栈的深度:

	// 通过递归操作
public static long count = 0; public static void test(long i) {
System.out.println(count++);
test(i);
} public static void main(String[] args) {
test(count);
}

通过测试我们发现,栈的默认深度是7000左右。之后就会报OOM错误。

可以根据需求去调整栈的深度大小;

一个栈的深度大小,太大或太小都会有弊端,太小的话影响方法链调用的深度、太大的话在整个JAVA进程当中它能够创建这样一个的线程的数量是有限的,如果太大会影响到其他线程创建栈的深度。

通过前人的经验来看,最佳值设置到5000左右就可以了。可以通过JVM参数去设置。

赵小胖个人博客

2-JVM内存模型的更多相关文章

  1. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  2. JVM内存模型和性能优化 转

    JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...

  3. JVM内存模型和性能优化

    JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...

  4. JVM初探 -JVM内存模型

    JVM初探 -JVM内存模型 标签 : JVM JVM是每个Java开发每天都会接触到的东西, 其相关知识也应该是每个人都要深入了解的. 但接触了很多人发现: 或了解片面或知识体系陈旧. 因此最近抽时 ...

  5. JVM内存模型和关键参数设置

    一. JVM内存模型: Jvm内存模型是学好Java很重要的一部分,该部分学习能让我们在系统运维的时候,或者优化服务器的时候能够有方法,懂原理. 二. Jvm关键参数: 1. 堆大小设置参数: -Xm ...

  6. 记录JVM内存模型,参数含义和优化

    一.JVM内存模型 (图片来自网络) 根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) Perm (永久代) 其中New和Tenured属于堆内存,堆内存会从J ...

  7. 【转】JVM内存模型

    http://longdick.iteye.com/blog/473866 图解JVM内存模型 博客分类: JVM JVM活动SUN  /** *  转载请注明作者longdick    http:/ ...

  8. jvm内存模型和内存分配

    1.什么是jvm? (1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的. (2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和 ...

  9. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  10. Java基础知识强化100:JVM 内存模型

    一. JVM内存模型总体架构图:  方法区和堆由所有线程共享,其他区域都是线程私有的 二. JVM内存模型的结构分析: 1. 类装载器(classLoader) 类装载器,它是在java虚拟机中用途是 ...

随机推荐

  1. node实现防盗链

    什么是防盗链 盗链,顾名思义就是盗窃链接,就是在他人未经允许的情况下,去使用他人站点的任何图片,视频,内容等资源,来借此提升已用的站点的活跃度,严重损坏了别人的利益.那么防盗链就是采用一些办法阻止自己 ...

  2. 概率专题_概率/ 数学_基础题_ABEI

    上周三讲了概率和概率dp.如果没有涉及其他综合算法,概率这种题主要是思维,先把这部分的东西写完 给个题目链接:https://vjudge.net/contest/365300#problem Hea ...

  3. Git应用详解第九讲:Git cherry-pick与Git rebase

    前言 前情提要:Git应用详解第八讲:Git标签.别名与Git gc 这一节主要介绍git cherry-pick与git rebase的原理及使用. 一.Git cherry-pick Git ch ...

  4. stand up meeting 11/25/2015 暨sprint2总结

    今天在课堂上进行了小组项目的阶段性总结,这两天小组内也是频繁的开会,具体细节我们已经反复核查,具体不表~ sprint2个人工作总结: 冯晓云:完成了必应词典在线查词api的调用和网络状况的检测:完成 ...

  5. bluecms v1.6 sp1 代码审计学习

    前言 正式开始代码审计的学习,拓宽自己的知识面.代码审计学习的动力也是来自团队里的王叹之师傅,向王叹之师傅学习. 这里参考了一些前辈,师傅的复现经验和bluecms审计的心得 安装 install.p ...

  6. Spring5:概念

    1.Spring优点 spring是一个开源的免费的框架 spring是一个轻量级的 非入侵式的框架 控制反转(IOC).面向切面(AOP) 支持事务的处理,对框架整合的支持 **总之:spring就 ...

  7. JasperReports入门教程(四):多数据源

    JasperReports入门教程(四):多数据源 背景 在报表使用中,一个页面需要打印多个表格,每个表格分别使用不同的数据源是很常见的一个需求.假如我们现在有一个需求如下:需要在一个报表同时打印所有 ...

  8. python信息收集(二)

        在第二层主机发现中,除了使用arping命令外,还可以使用Kali下自带的一个工具----netdiscover.      netdiscover是一个专门用于二层主机发现的工具,它有两种扫 ...

  9. SpringBoot【新手学习记录篇】

    1. 启动方式: 在idea中的application.java右键run as 命令行进入项目目录,使用命令 mvn spring-boot:run 使用mvn install进行打包,然后进入ta ...

  10. 9个小技巧让你的 if else看起来更优雅

    if else 是我们写代码时,使用频率最高的关键词之一,然而有时过多的 if else 会让我们感到脑壳疼,例如下面这个伪代码: 是不是很奔溃?虽然他是伪代码,并且看起来也很夸张,但在现实中,当我们 ...