JVM概况


JVM

学习目的

  • 有效防止内存泄漏
  • 优化线程锁的使用
  • 科学地进行内存回收
  • 提高系统吞吐量
  • 降低延时,提高性能

字节码底层执行顺序

在主流的JVM(如HotSpot)中实现了两种执行方式

代码执行方式

  • 热点代码 : 一般泛指循坏或者高频使用的方法
  • 解释执行器 : 负责将字节码翻译成机械码并执行
  • 编译执行器 : 负责即时编译(just-in-time compilation , JIT)

JIT :

用以提高代码效率,基于这种技术,字节码编译成平台相关的原生机器码,并进行各个层次的优化。这些机器码会被缓存起来,以便下次快速使用(会增加内存负担)

JVM的运行模式

cmd中 java -version 查看

Server模式(64bit 默认)

  • 启动速度慢,进入稳定期后速度相比较更快
  • 重量级虚拟机(对锁\内存等使用方面进行优化)

Client模式

  • 启动速度快,稳定后速度相对速度慢
  • 轻量级虚拟机

JVM架构

主要有三大部分

  • 类加载区:加载类到内存
  • 运行时数据区:负责存储数据信息
  • 执行引擎:负责调用对象执行业务(jit、gc、解释器)

JVM架构

运行内存架构

运行内存结构

堆区域

GC的主要管理区域

  • 年轻代首先进入

    优先放置其中的伊甸园区,待区域满了,GC启动,转入幸存区的From区

    • From和To区中相互转化,且永远有一个空的

    • 再一次GC(伊甸园和From皆有回收),From中没有被回收的资源转入To,

    • To转换为From,且资源年龄+1

    • 年龄大的资源被GC回收,进入老年代

  • 老年代进入方式

    1. 年轻代GC至老年代
    2. 年轻代空间满即伊甸园空间不足,创建对象时直接出生再老年代(部分小对象也有可能进入虚拟机栈)

方法区(元空间、持久代)

​ 在JDK8中是一块本地内存(脱离了JVM),由OS动态配置,可以手动设置最大空间

程序计数器

  • 线程启动时创建,线程私有
  • 记录当前正在执行的虚拟机字节码指令地址
  • 该区域不会存在内存溢出

  • 存储栈帧对象
  • 方法的一次调用就会经历一次压栈和出栈
  • 小对象(十几个bytes)且没有逃逸(没有全局声明)会创建在此
  • 容易在递归时(未使用尾递归优化)发生栈内存溢出

本地方法栈

调用本地的方法,java调用非java代码的接口

执行引擎

  • interpreter(解释器):即时运行,变编译边执行代码
  • JIT :缓存热点代码,下次调用免编译直接运行
  • 垃圾收集器:收集垃圾对象

调优概述

堆主要着手以下方面

  • -XMS 堆空间的最小大小

  • -XMX 堆空间的最大大小

  • -XX: NewSize 新生代最小空间

  • -XX: MAXNewSize 新生代最大空间

  • -XX: NewRatio 老年代和新生代的比值

  • -XX: SurvivorRatio eden 和 单个Survivor的比值 例如8 等于 eden :Survivor = 8 :2

  • -Xss 每个线程大小

方法区(JDK8)

  • -XX:MetaspaceSize 最小空间
  • -XX:MaxMetaspaceSize 最大空间

  • -Xss 越小可以创建的线程越多,注意OS对单个进程可以创建的线程数最多在3000-5000之间

常用监控工具

1、jps 进程监控工具

​ 查看虚拟机正在运行的进程信息,可追踪到应用进程ID 、启动类名、文件路径。

2、jstat性能监控工具

​ 用于监视内存各个区域的使用情况、垃圾回收情况

3、jinfo 参数配置监控工具

​ 查询和调整JVM 配置信息。

4、jmap内存监控工具

​ 生存堆内存快照文件,查询堆内存配置和使用状况。

5、jstatck线程监控工具

​ 生成虚拟机当前时刻的线程快照文件。

6、可视化工具VisualVM(类似的很多)

​ jdk自带,可以进行本地和远程监控


文章作者: hyy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hyy !
  目录