Java基础-虚拟机机和垃圾回收

虚拟机和垃圾回收

1、Java程序执行流程

.java----->(编译)----->.class----->(解释,通过虚拟机来完成)----->解释成机器码后再执行

在这里插入图片描述

通过类加载器(ClassLoader)将 .class 文件加载到虚拟机(Java Vitual Machine JVM).

JVM的组成部分:

  1. 执行引擎(Execution Engine);
  2. 本地方法接口(Native Interface);
  3. 本地方法库(Native Libraries);
  4. 运行时数据区(Runtime Data Area); 包括:栈内存、堆内存等等。

2、虚拟机机

虚拟机(英语:virtual machine),在计算机科学中的体系结构里,是指一种特殊的软件,可以在计算机平台终端用户之间创建一种环境,而终端用户则是基于虚拟机这个软件所创建的环境来操作其它软件。虚拟机(VM)是计算机系统的仿真器,通过软件模拟具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统,能提供物理计算机的功能。

系统虚拟机:如VMware

程序虚拟机:如Java虚拟机(解析字节码)

了解三大虚拟机:

  • SUN 公司的 HotSpot;
  • BEA公司的 JRockit; (WebLogic)
  • IBM的 JVM;

从JDK 1.8开始,HotSpot和JRockit两者结合成现在的HotSpot;

在这里插入图片描述

在这里插入图片描述

3、运行时数据区

在这里插入图片描述

堆内存:保存所有引用数据的真实信息,属于共享区;

栈内存:基本类型、运算、指向堆内存的指针;

方法区:存储类的信息、常量池、方法数据、方法代码,也属于共享区;

程序计数器:是一个非常小的内存空间,用来保证程序依次执行;

本地方法栈:与虚拟机栈发挥的作用非常类似,只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为使用到的本地操作系统方法(Native)服务;

堆和方法区是所有线程共享的;

栈、程序计数器、本地方法栈是每个线程独享的;
运行时数据区就是java内存管理,java能管理的地方只在java运行时数据区,其他的我们无法控制;

关键是在堆内存中,如果想要真正做到对程序理解,就需要对堆内存进行一定的控制。

堆解决的是数据存储的问题,即数据怎么放,放在哪。

方法区则是辅助堆栈的一次永久区(Perm),解决堆栈信息的产生,如:我们创建一个新的Person对象,那么Person类的一些信息(类信息、静态信息都存在于方法区中)

Person p1 = new Person();
Person p2 = new Person();
  • Person类被实例化后,就被存储到了java堆内存中;
  • 当我们要使用Person对象实例时都是用该实例对象的引用 p 即引用变量

图一

4、栈内存

在这里插入图片描述

一个线程一个单独的栈(私有);

一个方法分配一个单独的栈帧;

当产生一个方法调用的时候,原本的方法会入栈,当方法执行完毕之后,方法将会进行栈帧的出栈,和垃圾回收无关。

5、对内存(垃圾回收的主战场)

注意:JDK 1.8 之后就不存在永久代了

在这里插入图片描述

堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,该内存区域存放了对象实例及数组(但不是所有的对象实例都在堆中)。其大小通过-Xms(最小值)和-Xmx(最大值)参数设置(最大最小值都要小于1G),前者为启动时申请的最小内存,默认为操作系统物理内存的1/64,后者为JVM可申请的最大内存,默认为物理内存的1/4,默认当空余堆内存小于40%时,JVM会增大堆内存到-Xmx指定的大小 。

新生代:

分为 eden区 + 两个大小相同的存活期 s0 , s1;

  1. 所有使用new关键字实例出来的对象,一定会在伊甸园区(eden)区进行保存,除非对象太大存不下;
  2. 存活期分为两个大小相等的存活区,存活区保存的一定是在伊甸园区保存很久,并且经过几次GC后还存活下来的活跃对象,存活区一定有两块大小相等的空间,目的是一块存活区未来晋升,另一块存活区为了对象回收。这两块空间一定有一块是空的,在新生代中使用的是Minor GC,这种GC采用的是复制算法。

老年代:

主要接受由新生代发送过来的对象,一般情况下经过了数次 Minor GC 之后还会保存下来的对象才会进入到老年代。每次进行Minor GC 后存活下来的对象,年龄都会 +1,到了一定的年龄后(默认是15),就将进入老年代

如果要保存的对象的大小超过了伊甸园区的大小,此对象也将直接保存在老年代之中,当老年代空间不足时,将引发“Major GC” 即 “Full GC” 全部由垃圾回收器回收。

6、JVM 垃圾回收流程

在这里插入图片描述

在整个 GC 流程里,最需要处理的就是新生代和老年代的内存清理操作。

  1. 当发现有一个新的对象产生,就需要给该对象分配内存空间,于是就需要为该对象进行内存空间的申请;

  2. 首先会判断伊甸园区是否有内存空间,如果正好有内存空间,则将新对象保存在伊甸园区;

  3. 如果伊甸园区的内存不足,那么会自动执行一次 Minor GC (小的垃圾回收),将伊甸园区无用的内存空间进行清理,当清理之后会继续判断内存空间是否充足? 如果充足的话就会把新建的对象保存在伊甸园区;

  4. 如果执行了一次 Minor GC 后内存空间仍然不足,那么这个时候就会进行存活区判断,如果存活区有内存空间剩余,则将伊甸园区的部分对象保存在存活区,那么随后会继续判断伊甸园区的内存空间是否足够,如果足够则在伊甸园区进行空间分配;

  5. 如果此时存活区也没有内存空间了,则开始判断老年代,如果此时老年代空间充足,则将存活区的活跃对象保存在老年代,而后存活区就会有空间剩余,随后伊甸园区将活跃对象保存在存活区中,而后在伊甸园区里为新对象开辟内存空间;

  6. 如果这个时候老年代的内存也满了的话,那么这个时候就会进行 Major GC(Full GC),进行老年代的内存清理;

  7. 如果老年代执行了 Full GC 后,依然无法进行对象的保存,就会产生 OOM异常 - - OutOfMemoryError;

7、虚拟机参数调优

堆内存空间调整参数

no参数名称描述
01-Xms设置初始分配大小,默认为物理空间的 1/64
02-Xmx最大分配内存,默认为物理空间的 1/4
03-XX:+PrintGCDetails输出详细的GC处理日志
04-XX:+PrintGCTimeStamps输出GC的时间戳信息
05-XX:+PrintGCDateStamps输出GC的时间戳信息(以日期的形式)
06-XX:+PrintHeapAtGC在GC处理的前后打印堆内存信息
07-Xloggc:保存路径设置日志信息保存文件

新生代内存调整参数:

no参数名称描述
01-Xmn设置新生代堆内存大小,默认是物理内存的 1/64
02-Xss设置每个线程栈大小,JDK 1.5之后默认为每个线程分配1M的栈大小,减小此数值可以产生更多的线程对象,但是不能无限生成。
03-XX:SurvivorRatio设置 eden 与 survivor空间的大小比例,默认为8:1:1,不建议修改
04-XX:NewSize设置新生代内存区大小
05-XX:NewRatio设置新生代与老年代的比率

老年代内存调整参数:

no参数名称描述
01-XX:NerRatio设置新生代与老年代的比率
02-XX:+UseAdaptiveSizePolicy控制是否采用动态控制策略,如果动态控制,则动态调整Java堆中各个区域的大小以及进入老年代的年龄
03-XX:PertenureSizeThreshold控制直接升入老年代的对象大小,大于这个值的对象会直接进入老年代

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值