前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

JVM

作者头像
OPice
发布2019-12-16 18:03:17
5150
发布2019-12-16 18:03:17
举报
文章被收录于专栏:D·技术专栏

什么是JVM

   JVM是java virtual mechine 的缩写,是在真实的计算机基础上模拟计算机的各种功能的一种实现,JVM的本身对于计算机而言也是一个程序。    Java的跨平台性其实是依赖JVM,也就是在任何计算机平台安装JVM,就可以执行java的字节码文件,达到了"一处编译,处处运行"。

JVM的组成部分

JVM由五部分组成:堆、栈:(虚拟机栈、本地方法栈)、方法区、程序计数器。

image.png

:根据对象的声明周期不同,划分不一样的区域:新生代、老年代、永久代(1.8之后被元空间取代)。新生代存放的一些朝生夕死的对象,老年代存放一些大对象或者多次GC后还存在的对象,永久代存放一些类信息、常量、静态变量等数据。这样划分的目的,是为了更好的回收内存,对于一些需要频繁回收,声明周期短的对象,放在新生代中。

image.png

其中Eden区和From Survivor区、To Survivor区比例8:1:1,GC开始时对象只会存在Eden和From区,To区是空的。GC进行时,Eden区存活的对象会被复制到To区,From区会根据对象的年龄来决定去向,默认15,超过会将From区移到老年代,否则移到To 区。 接着会将Eden和From 区清空,然后将To 区域的对象重新复制到新的From区域。其中如果To区没有足够的空间来保存上次新生代存活下的对象时,有老年代担保将这些对象放在老年代中。

虚拟机栈:是用于描述java方法执行的内存模型。每个方法在执行的时候都会创建一个栈帧,栈帧的组成:局部变量表、操作数栈、动态连接、方法出口。每个方法执行的过程就是一个压栈和出栈的过程。

image.png

每个线程有独自的虚拟机栈,线程之间隔离。若单个线程请求栈的深度大于虚拟机允许的深度,会抛出StackOverFlowError。

本地方法栈 :本地方法栈于虚拟机栈类似,不同的是调用的native方法。

方法区:类的信息、常量、静态变量等信息,1.7开始,字符串常量池移到java heap中,1.8 开始元空间取代永久代。方法区只是一种规范,一开始HotSpot只是用永久代来实现方法区,能够省去这块内存回收的逻辑。但是永久代受-XX:MaxPermize大小限制,会出现OOM。

程序计数器:较小的一块空间,主要是记录程序执行字节码的行号指示器。对于Java的多线程而言,是通过切换分配处理器执行时间来实现的,所以为了线程切换后能够恢复到正确的位置,每条线程都有一个程序计数器。

垃圾收集器和内存分配策略

  对于Java来说,程序计数器、虚拟机栈、本地方法栈这些是伴随着线程一块销毁,而堆和方法区是需要回收的,针对这块内存JVM如何分配,如何收入,下面就来一块看下。

  首先,先搞明白这三个问题:

  • 哪些内存需要回收?
  • 什么时候回收?
  • 如何回收
  1. 哪些内存需要回收?   堆和方法区,最主要的就是堆,每次GC就会回收堆里70%-80%左右内存。堆里主要存放的就是对象和常量池,所以先要判断哪些对象和方法区是可以回收的。 判断对象已死的方式:
  • 引用计数法 如果对象被引用+1,引用失效-1,当值为0时对象可回收,这种方式的缺陷在于如果两个对象互相引用,比如: a=b; b=a; a=null; b=null; 这时对象引用不为0,事实上a,b两个对象都可以回收的。
  • 可达性算法分析 以“GC Root” 为起点,往下如果引用链中没有该对象,则回收该对象,即使被finalize的对象,也是有可能逃离回收的命运,真正的回收是需要经过两次标记,当第一次finalize的时候,会将对象发在F-Queue队列中,会对队列再次执行finalize这时对象如果被引用就会逃离被回收的命运。

image.png

GC Root的对象:虚拟机栈的局部变量表的所有对象;方法区静态属性的所有对象;方法区常量的所有对象;Native方法的所有对象。

  • 引用类型:强、弱、软、虚 只是用做标记对象的状态,强引用:抛出OOM也不会回收 ;弱引用:在抛出OOM之前会尝试回收弱引用的对用,多用于图片和网站缓存;软引用:存活在下次GC之前;虚引用:没有实际应用场景,随时可以被回收。
  1. 什么时候回收?   对象在被标记不可达对象时,也不会立即被回收,回收的动作是发生在对象分配空间不足时,才会真正的执行回收动作。
  2. 如何回收?   针对不同代回收的机制不同,新生代都是朝生夕死的对象使用的是复制算法,将Eden区和From区没有被回收的区域复制到To区,然后将Eden和From清空,在将To区的对象复制到From区。   老年代的回收方式,对于一些大对象考虑内存的问题,适用标记清除和标记整理。

工具和相关参数配置

java自带的命令

  • jps 列出虚拟机进程
  • jstat 虚拟机监视信息统计工具
  • jmap java某个进程所有对象的信息
  • jstack java堆栈跟踪工具 图形化工具 jconsole

参数配置

打印trace信息

参数

描述

-XX:+PrintGC或者-verbose:gc

打印GC日志

-XX:+PrintGCDetails

GC详细日志

-XX:+PrintGCTimeStamps

gc的时间戳

-Xloggc:/log/gc.log

gc文件的目录

-XX:+PrintHeapAtGC

打印GC前后堆的日志

-XX:TraceClassLoading

监控类的加载

堆的分配参数 堆的内存= 年轻代+老年代+永久代 永久代固定值64m,年轻代建议占3/8。

参数

描述

-Xmx,-Xms

堆的最大值和最小值,开发过程中经常配置为一样的,是为了GC后不需要重新分配造成资源浪费

-XX:+HeapDumpOnOutOfMemoryError、-XX:+HeapDumpPath 查看系统dump的时候发生什么,导出OOM的路径。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是JVM
  • JVM的组成部分
  • 垃圾收集器和内存分配策略
  • 工具和相关参数配置
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档