一,垃圾回收,如何判断哪些对象当作垃圾需要被回收?
在内存中,要进行垃圾回收,首先我们先明确什么是垃圾?内存中不再使用的内存空间我们都称为垃圾。
如何判断该对象是否需要垃圾回收?
可达性分析算法也称根搜索路径算法:从GC Root对象为起点,向下开始搜索,如果一个对象到GC Root没有任何引用链相连时,则说明此对象不可用,也即给定一个集合的引用作为根出发,通过引用关系遍历对象,能被遍历的对象则判定为存活,没有遍历到的则判定为死亡。
上面我们提到GC root,哪些对象可以作为GC Root对象?
《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》一书中提到的 GC Roots 为:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象;
2.方法区中的类静态属性引用的对象
3.方法区中的常量引用的对象
4.原生方法栈(Native Method Stack)中 JNI 中引用的对象。
二,盘点JVM的系统默认参数值?
JVM参数类型共分为三类,前两类了解即可,我们详细介绍第三类:
- 标配参数
- X参数
- xx参数(重点)
xx参数:
1)boolean类型:格式为: -xx:+或- 某个属性值 +表示开启 -表示关闭
举一个demo来说:
public class TestGC {
public static void main(String[] args) throws InterruptedException {
System.out.println("testGC");
Thread.sleep(Integer.MAX_VALUE);
}
}
对于这个简单的语句输出程序,查看他的运行时的进程,使用命令: jps-l,运行结果如下所示:
13184
6416 org.jetbrains.jps.cmdline.Launcher
6308 org.jetbrains.idea.maven.server.RemoteMavenServer
1112 org.jetbrains.jps.cmdline.Launcher
13320 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
9256 practice.TestGC
3660 sun.tools.jps.Jps
其中9256就是我们上面TestGC程序运行的进程号。有了这个进程号以后,我们可以使用 jinfo -flag 配置项 进程号命令查看当前运行程序的配置信息,具体的参数值是多少。例如执行jinfo -flag PrintGCDetails 9256命令以后,该命令表示当前这个进程是否开启PrintGCDetails这个参数,打印出来的信息如下:
D:\code\designpattern>jinfo -flag PrintGCDetails 19708
-XX:-PrintGCDetails
-PrintGCDetails说明PrintGCDetails未开启
这次我们带运行参数运行此程序:
在执行:jps-l 和 jinfo 命令,执行结果如下:
D:\code\designpattern>jps -l
13184
15904 org.jetbrains.jps.cmdline.Launcher
6416 org.jetbrains.jps.cmdline.Launcher
6308 org.jetbrains.idea.maven.server.RemoteMavenServer
13320 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
14732 sun.tools.jps.Jps
19708 practice.TestGC
D:\code\designpattern>jinfo -flag PrintGCDetails 19708
-XX:+PrintGCDetails
+PrintGCDetails说明PrintGCDetails已开启,使用此方法可以配置boolean类型的参数是否开启。
2)K-V类型:格式为:-xx:属性key=属性值value
再一次运行上面的程序以后,执行一下的命令:
D:\code\designpattern>jps -l
13184
6416 org.jetbrains.jps.cmdline.Launcher
19972 sun.tools.jps.Jps
6308 org.jetbrains.idea.maven.server.RemoteMavenServer
13320 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
20072 org.jetbrains.jps.cmdline.Launcher
18524 practice.TestGC
D:\code\designpattern>jinfo -flag MetaspaceSize 18524
-XX:MetaspaceSize=21807104
说明MetaSpace参数在我们没有设定的情况下,默认大小为21807104
我们将修改MetaSpace大小修改为1024M呢,如何修改?加入运行参数如下
再次执行命令:
D:\code\designpattern>jps -l
13184
14240 practice.TestGC
6416 org.jetbrains.jps.cmdline.Launcher
6308 org.jetbrains.idea.maven.server.RemoteMavenServer
7684 org.jetbrains.jps.cmdline.Launcher
13320 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
15356 sun.tools.jps.Jps
D:\code\designpattern>jinfo -flag MetaspaceSize 14240
-XX:MetaspaceSize=1073741824
可以看到MetaspaceSize是我们修改以后的值了,使用此K-V类型可以配置其他的JVM参数值的大小。。
执行命令:jinfo -flags 进程号 可以查看JVM默认的参数配置和我们在运行时加的参数配置。
D:\code\designpattern>jps -l
13184
6416 org.jetbrains.jps.cmdline.Launcher
6624 org.jetbrains.jps.cmdline.Launcher
6308 org.jetbrains.idea.maven.server.RemoteMavenServer
13320 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
13420 sun.tools.jps.Jps
5500 practice.TestGC
D:\code\designpattern>jinfo -flags 5500
Attaching to process ID 5500, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
//JVM 默认的参数配置
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=130023424 -XX:MaxHeapSize=2048917504 -XX:MaxNewSize=682622976 -XX:
MetaspaceSize=1073741824 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=42991616 -XX:OldSize=87031808 -XX:+UseCompressedClassPointers -X
X:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
//运行的JVM 参数配置
Command line: -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:55973,suspend=y,server=n -XX:MetaspaceSize=1024m -javaagent:C:
\Users\ding\.IntelliJIdea2018.3\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8
上面说了这么多也没说到底如何查看jvm默认的参数,那么接下来我们在执行命令:
java -XX:+PrintFlagsInitial,查看初始化默认配置。
=:表示初始化值
java -XX:+PrintFlagsFinal查看jvm或用户修改更新以后的配置
:=:修改更新以后的值
如下图的最大推内存大小,默认情况下根据每台电脑去配置,所以前面是:=
-XX:+PrintCommandLineFlags查看JVM参数配置默认初始化参数
-XX:InitialHeapSize=128030144
-XX:MaxHeapSize=2048482304
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
三:基础参数的配置
Xms:等价于-XX:InitialHeapSize 初始化堆内存大小,默认占物理内存的1/64
Runtime.getRuntime().totalMemory();
-Xmx:等价于-XX:MaxlHeapSize 最大堆内存大小,默认占物理内存的1/4
Runtime.getRuntime().maxMemory();
-Xss:等价于-XX:ThreadStackSize 设置单个线程栈的大小
-Xmn:设置新生代的大小
-XX:MetaSpace:设置元空间的大小
-XX:PrintGCDetails:输出GC日志信息
YoungGC日志信息:
FullGC日志信息:
-XX:SurvivorRatio:设置新生代中eden区和s0和s1的空间大小
-XX:NewRatio:设置新生代和老年代的空间大小
-XX:MaxTenuringThreshold:设置垃圾最大年龄
三:四种引用
- 强引用:当内存不足时,JVM进行垃圾回收,对于强引用对象,就算发生OOM也不会对其进行回收。因此强引用是造成Java内存泄露的原因之一。
- 软引用:当内存充足时,不会被回收;当内存不足时,会被回收。
- 弱引用:不管内存是否够用,都会回收。
- 虚引用:与其他几种引用不同,如果一个对象仅持有虚引用,那么他就和没有任何引用一样,在任何时候都可能被垃圾回收器收集。get()总是返回null,虚引用必须和ReferenceQueue一起使用,虚引用对象被gc()以后,会被放到ReferenceQueue队列里。用户监控对象回收的场景下。