jvm在我们日常开发过程中比较少使用,但是当我们考虑到架构设计以及系统层面流程开发时,就不得不考虑jvm内存模型,JVM规定java运行的内存申请、分配、管理的策略,特别是在性能调优,系统异常排查是经常使用,所以要懂JVM才能搭建高效稳定的系统

参考经典JVM内存模型分五块:

1、Method Area:

主要存放类加载信息(类的生命周期:加载、校验、准备、解析、初始化、使用、卸载)、常量、静态变量以及JIT编译后的class等数据,方法区的特点有几个:全局共享、永久(伴随JVM生命周期,一般不会发生gc),此处不允许垃圾回收机制,也不允许扩展,当方法区内存不够时会发生OutOfMemoryError,个人没怎么使用调节方法去内存

常见的方法区设置大小,目前常用JDK8以上元空间,如下设置常量池大小,但是不常用,没有实战经验,

-XX:MetaSpaceSize和-XX:MaxMetaspaceSize=5M

jdk7之前用如下设置大小

-XX:PermSize和-XX:MaxPermSize

2、Heap

堆内存分配和系统的运行效率息息相关,也是OOM的主要来源,此内存存放类的实例对象,一般堆内存是可扩展,常用设置堆的大小如下

-Xms    -Xmx

堆又分为几个区新生代eden和老年代(jdk7之前是老年代),它两占用堆空间比例使用 –XX:NewRatio=n指定大小,此外常用线上生成堆快照指令如下:

jmap -dump:live,format=b,file=heap-dump.bin <pid>

新生代

新生代又分为Eden、from survivor(S0)、to survivor(S1),它们之间的比例一般是8:1:1,我们常用的几种gc时期minor gc就发生在Eden,young gc 发生在整个新生代的Eden、s0或者s1.整个区的大小指定是-Xmn指定大小,此处一般常调整大小

老年代

新建的对象一般优先进去eden,新生代一般会发生minor gc新建的大对象无法在新生代存放时直接过度老年代,majoy gc就发生在老年代

对此可能有人疑问,full gc又是如何发生的呢?不用想的话当然是老年代发生full gc,当新生代对象没有被gc root关联时,经过多次垃圾回收没有被回收存放到老年代时,由于老年代发生major gc也无法回收,堆内存无法存储将会导致full gc,以便腾出空间。发生full gc是非常严重的问题,直接导致应用变慢甚至应用停顿。

新生代默认发生15次 young gc,14次之后若不被回收将会进入老年代,新生代和老年代以及发生OOM一般流程如下,我们常设置新生代和老年代占用比例,其实是设置young gc的频率来达到一定效果。

heap调优有如下参数,一般不可能完美流程,根据CAP原则(一致性consistency、可用性availability和分区容错性partition tolerance),只能根据应用自身情况设置

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof 设置jvm堆异常快照的地址
-Xms  -Xmx 设置堆最大值和最小值
-XX:MaxPermSize=n 持久代大小
–XX:NewRatio=n 设置新生代和老年代的占用比例
-XX:SurvivorRatio eden和survivor比例
-XX:MaxTenuringThreshold young gc次数,默认15
   
-XX:+UseParallelGC 并行收集器
-XX:+UseSerialGC 串行收集器
-XX:+UseG1GC 使用G1算法
-XX:MaxGCPauseMillis G1最大停顿时间,毫秒
   
-XX:+PrintGC 打印gc日志
-XX:+PrintGCDetails 垃圾回收数据详情
-XX:+PrintGCTimeStamps 回收时间,可以上并存
-Xloggc:filepath 记录gc详细日志文件

常用的jvm堆调试工具有:

arthas 阿里巴巴集成工具

top 命令查找java进程

jconsole远程或者本地调试

jvisualvm 可视化监控

jstack -l pid >> filepath  栈信息

jmap -dump:live,format=b,file=heap-dump.bin <pid>  生成快照

jhat 分析map信息

3、虚拟机栈VM Stack

栈的概念大家应该就会想到入栈和出栈的概念,其实在方法调用过程就是栈帧的入栈和出栈,虚拟机栈的主要内容是局部信息,线程私有的,比如局部变量、操作栈、动态连接、方法返回地址之类的。此处常见就是栈的深度超出限定即StackOverflowError,比如我们看如下代码:

package com.jvm;public class MainTest {public static void main(String[] args) throws InterruptedException {try {addStackLength();} catch (Throwable e) {System.out.println("stackLength=" + stackLength);e.printStackTrace();}try {stackLength = 0;addStackLength();} catch (Throwable e) {System.out.println("stackLength=" + stackLength);//e.printStackTrace();}}private static int stackLength = 0;public static void addStackLength() {stackLength++;MainTest.addStackLength();}
}

上面代码将会输出

stackLength=23366
java.lang.StackOverflowError

stackLength=62790

java.lang.StackOverflowError

会发现诡异问题,上面每次运行栈的深度是不固定的,这个和JIT有关,详细请查看JIT

用javap -verbose filepath上面代码方法如下

public static void addStackLength();descriptor: ()Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=0, args_size=0    // 栈最大深度2 ,局部变量0 ,入参00: getstatic     #9                  // Field stackLength:I3: iconst_1                 // 常量值入栈14: iadd                    // ++5: putstatic     #9                  // Field stackLength:I 设置变量值8: invokestatic  #2                  // Method addStackLength:()V 调用静态方法V11: returnLineNumberTable:line 23: 0line 24: 8line 25: 11static {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: iconst_01: putstatic     #9                  // Field stackLength:I4: returnLineNumberTable:line 20: 0
}

从中可以看出每个方法调用时都是虚拟机栈的入栈和出栈过程。

4、本地方法栈

本地方法栈主要和Native方法服务有关,这里不受JVM的约束,可以自主阅读相关材料!

5、程序计数器

程序计数器主要和CPU打交道一样,记录虚拟机的执行指令的偏移量和行号指令器等,这里没有内存溢出的概念!

总结

虚拟机使用场景不对,但是很有价值和意义,个人在搭建一次某银行中小型系统过程中使用比较多的是堆内存优化还有排查的简单工具使用。还有个人编写能力也不是很好,如有不足之处多多指教!

JVM内存模型-回忆学习总结相关推荐

  1. 深入理解JAVA虚拟机学习笔记(一)JVM内存模型

    摘要:   上周末搬家后,家里的宽带一直没弄好,跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状 ...

  2. JVM学习(三)JVM内存模型

    引言 本文希望以另外一种维度的思考方式来学习JVM内存模型,希望自己能从设计原理的维度考虑为什么存在?有什么价值?解决什么问题? 在学习JVM内存模型之前,先回顾下前面两章的内容点类加载器机制与类加载 ...

  3. JVM内存模型学习(入门)

    新手Java开发,探究比较浅,只是记录学习, 如果对您有帮助,荣幸之至.如有大佬,请指教 JVM内存模型 JVM运行机制 什么是内存模型 程序计数器(线程私有) Java虚拟机栈(线程私有) 本地方法 ...

  4. 解释 i = i++为什么等于本身的问题——JVM内存模型学习笔记

    前段时间在扫题的时遇到类似以下的例子: public class Test {public static void main(String [] args) {int i = 1 ;//int j = ...

  5. JVM内存模型深度讲解(Java学习笔记)

    JDK,JRE,JVM之间的关系 JDK(Java Development Kit)就是java 开发工具,从图中可以看到,JDK包含JRE,Java基础类库和Java工具,这是给开发者使用的产品. ...

  6. JVM虚拟机学习 - JVM类加载,JVM内存模型,JVM性能分析工具

    JVM虚拟机 二 JVM类加载 类的生命周期 加载: ​ 加载class文件到二进制字节流,然后再将二进制字节流转化为方法区的运行时数据结构,生成一个对应的Class对象作为类各种数据的访问入口. 链 ...

  7. 深入理解Java虚拟机学习笔记-1.JVM内存模型

    JVM内存模型 1.内存模型结构图 名称 特征 作用 配置参数 异常 程序计数器 占用内存小,线程私有, 生命周期与线程相同 大致为字节码行号指示器 无 无 虚拟机栈 线程私有,生命周期与线程相同,使 ...

  8. JVM内存模型 和 Java内存模型 对比学习

    前言 首先要知道这两者不是同一个东西,Jvm内存模型 也叫 Java内存区域.Java运行时数据区域 而Java内存模型 是 JMM (Java Memory Model,简称 JMM),是定义了线程 ...

  9. 面试必会系列 - 1.7 JVM 内存模型

    本文已收录至 Github(MD-Notes),若博客中图片模糊或打不开,可以来我的 Github 仓库,包含了完整图文:https://github.com/HanquanHq/MD-Notes,涵 ...

最新文章

  1. 科宇扫地机器人_我的三年16台智能扫地机器人使用回忆录 篇四:扫地谁更精准更干净?新一代3D视讯+激光成像 PK 老式激光扫描,万字实测对比分享...
  2. Python Module — WSME
  3. 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)
  4. linux开启防火墙特定端口号
  5. orbeon form 通过 url 的方式同第三方应用集成的开发明细
  6. Spring项目的按层打包已过时
  7. delphi ,安装插件
  8. linux下搭建博客Day8
  9. 第一讲:使用html5——canvas绘制奥运五环
  10. 测试网速_Azure AWS Google Cloud服务网速及Ping值延时在线测试
  11. “时间的朋友”2017跨年演讲全回顾
  12. python 对比matlab_全面对比 MATLAB、Julia、Python,谁在科学计算中更胜一筹?
  13. verilog之分频大全
  14. 轻松玩转Scratch 3.0编程课程计划
  15. 2019年最新WHQL认证申请流程
  16. 自定义键盘KeyboardView如何添加点击音效
  17. 进程---什么是多进程
  18. 利用三点坐标加海伦公式求三角形面积
  19. 英语总结——新的开始
  20. SVN服务端以及客户端的安装包(含汉化包)

热门文章

  1. 吉天工业数据自动采集系统(DCS)实现工业4.0的智慧工厂
  2. 手把手教你快速搭建私服环境
  3. 联想小新蓝屏问题解决方法三步走!
  4. 实在受不了360流氓浏览器用了10年终于不用了
  5. 业余爱好者,学习JAVA在实际中有什么用途?
  6. Bootstrap入门使用
  7. Google Earth Engine(GEE)——GEE最全介绍(7000字长文)初学者福音!
  8. 6.5 静态组织架构
  9. 目标检测论文解读复现之十五:基于YOLOv5的光学遥感图像舰船 目标检测算法
  10. 当笔记本是无线连接网络时,如何正确配置virtualbox的上网问题