1、JVM与GC

jVM的空间

JVM有一个称为垃圾回收器的低级线程,这个线程在后台不断地运行,自动寻找在Java程序中不再被使用的对象,并释放这些对象的内存。这种内存回收的过程被称为垃圾回收(Garbage Collection)

img

空间比例

新生代中空间比例:Eden:form:to = 8:1:1

新生代和老年代的比例:young:old = 1:2

垃圾回收的目的

垃圾回收的算法

判断是否可回收的算法

回收算法

GC相关API

finalize()

final、finally、finalize()的区别

System.gc(),Runtime.gc()

内存泄漏和内存溢出

内存溢出 out of memory

是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory

内存泄露 memory leak

是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光

另外,内存泄漏memory leak最终会导致内存溢出out of memory

内存泄漏

1、长生命周期对象持有短生命周期对象,例如:

public class Demo{
    private Object object;
    public void setObject(){
        object = new Object();
    }
}
/* 此时执行了setObject方法后
 * 如果Demo的实例没有被回收,那么object对象会一直存在与内存中
 */

2、集合中的内存泄露,我们有的时候会声明静态的集合对象,而集合中的每个元素指向一个对象,集合不会被回收,导致里面元素指向的对象也不会被回收

3、连接中的内存泄漏,对于这些连接对象(数据库链接、网络连接、IO连接),除非我们显示的调用了close方法,否则这个对象不会被GC回收

Java代码的优化

1、几种for循环的区别

//这种for循环,会在每一轮循环之前重新计算list的size
for(int i=0;i<list.size();i++)
//这种for循环,只在第一次循环前计算长度,性能较高
for(int i=0,len=list.size();i<len;i++)

2、String字符串的相加

简单的字符串相加,结果每次都会创建一个新的对象,对于频繁进行相加操作的字符串,不建议使用String,而是使用StringBuffer或StringBuider

3、尽可能使用局部变量

非必要情况,不要使用全局变量或实例变量,局部变量随着方法的结束,就会准备进行回收

4、及时关闭流、连接

5、尽量使用懒加载策略,使用的时候再创建

6、慎用异常,因为异常的抛出之前,也需要创建对象

jvisualvm的使用

一、启动jvisualvm

1.1、找到jdk安装目录中的jvisualvm.exe,并启动

image-20210919211916704

二、安装Visual GC插件

2.1、打开面板上的工具-插件

image-20210919212333914

2.2、安装Visual GC插件

2.3、如果安装失败,可以手动安装

进入插件中心,在右边选择自己的jdk版本:https://visualvm.github.io/pluginscenters.html

点击进去,下载插件

选择自己下载的插件,进行安装

image-20210919212951603

三、查看GC

image-20210919213129339

JVM中GC的执行过程

1、新创建的对象,会优先放入新生代的Eden区

2、GC执行,会将所有Eden区的存活对象,复制到From区,清空Eden区

3、GC再次执行,回收完无用对象后,会将From区的对象全部复制到To区,清空From区

4、GC再次执行,回收完无用对象后,会将To区的对象全部复制到From区,清空To区,3、4步的作用是为了减少内存空间碎片,也就是防止内存不连续,导致内存溢出

5、GC反复执行3、4步,如果对象执行3、4超过15次或To区满了,会将所有对象移入老年代,S区(From和To)