JVM和GitHub

mac2025-05-04  17

JVM和GitHub

1、JVM垃圾回收的时候如何确定垃圾?是否知道什么是GC Roots?

垃圾:就是内存中已经不再被使用的空间 判断:引用计数法 枚举根节点做可达性分析(根搜索路径,包括:复制、标记清除、标记整理):以GC Roots对象作为起点,向下搜索,如果一个对象没有任何引用时(不可达),将被回收,反之可达,判定为存活。 可以作为GC Roots对象的有: 虚拟机栈(栈帧中的局部变量区,也叫局部变量)中引用的对象; 方法区中的类静态属性引用的对象; 方法区中常量引用的对象; 本地方法栈中JNI(Native方法)引用的对象。

2、JVM调优和参数配置,如何查看JVM系统默认值?

JVM的参数类型: 标配参数:java -version …… x参数: -Xint -->解释执行 -Xcomp -->第一次使用就编译成本地代码 -Xmixed -->混合模式 xx参数(重点): Boolean类型:--->+表示开启,-表示关闭 如:是否打印GC收集细节:-XX:-PrintGCDetails、-XX:+PrintGCDetails 是否使用串行垃圾回收器:-XX:-UseSerialGC、-XX:+UseSerialGC KV设值类型: 公式:-XX:属性key = 属性值value Case:-XX:MetaspaceSize=128m、-XX:MaxTenuringThreshold=15 jinfo举例,如何查看当前运行程序的配置 查看JVM的默认值: -XX:+PrintFlagsInitial 查看初始默认值 java -XX:+PrintFlagsInitial -version | java -XX:+PrintFlagsInitial -XX:+PrintFlagsFinal 查看修改更新后的值 -XX:+PrintFlagsFinal -version | -XX:+PrintFlagsFinal =--->表示没有修改过 :=-->表示修改过(JVM或人为) PrintFlagsFinal举例,运行java命令的同时打印出参数 -XX:+PrintCommandLineFlags

必须掌握: -XX:+PrintFlagsInitial -XX:+PrintFlagsFinal -XX:+PrintCommandLineFlags 常用参数: -Xms:初始化大小内存 -Xmx:最大分配内存 -Xss:设置单个线程的大小 -Xmn:设置年轻代大小 -XX:MetaspaceSize :元空间(Java8以后替代永久代) -XX:+PrintGCDetails -XX:SurvivorRatio -XX:NewRatio -XX:MaxTenuringThreshold :设置垃圾最大年龄

3、强引用、软引用、弱引用、虚引用分别是什么?

​ Java默认是强引用

强引用:JVM就算出现OOM也不会对该对象回收,死也不会回收 造成内存泄露 package com.itguigu; //强引用 public class StrongReferenceDemo { public static void main(String[] args) { Object obj1 = new Object();//这样定义的默认就是强引用 Object obj2 = obj1;//obj2引用赋值 obj1 = null;//置空 System.gc(); System.out.println(obj1);//null /* 因为是强引用:所以obj1被清理,与obj2没毛关系 */ System.out.println(obj2);//java.lang.Object@3f99bd52 } } 软引用:内存足够,则不收;内存不够,需要收;来保证不会发生OOM

package com.itguigu;

import java.lang.ref.SoftReference;

//软引用 public class SoftReferenceDemo { private byte[] bytes;

/** * 内存够用就保留,不够就回收 */ public static void softRef_Memory_Enough(){ Object o1 = new Object();//强引用 //软引用 SoftReference<Object> softReference = new SoftReference<>(o1); System.out.println(o1); System.out.println(softReference.get()); o1 = null; System.gc(); System.out.println(o1);//null //内存够用,软引用不会被回收 System.out.println(softReference.get());//java.lang.Object@3f99bd52 } /** * 超出内存,软引用被回收 * * -Xms5m -Xmx5m -XX:+PrintGCDetails */ public static void softRef_Memory_NotEnough(){ Object o1 = new Object();//强引用 //软引用 SoftReference<Object> softReference = new SoftReference<>(o1); System.out.println(o1); System.out.println(softReference.get()); o1 = null; System.gc(); try { //让内存空间不够 byte[] bytes = new byte[30 * 1024 * 1024]; } catch (Exception e) { e.printStackTrace(); } finally { System.out.println(o1);//null //内存不够用,软引用会被回收 System.out.println(softReference.get());//null } } public static void main(String[] args) { softRef_Memory_Enough(); System.out.println(); System.out.println(); System.out.println(); softRef_Memory_NotEnough(); } } 弱引用:无论内存是否够用,只要垃圾回收到来,一律回收 * 如果每次读取图片都从硬盘读取则会严重影响性能, * 如果一次全部加载到内存中又可能造成内存溢出; 使用软引用: 用一个HashMap来保存图片路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效的避免了OOM的问题。 Mao<String,SoftReference<Bitmap>> imageCache = new HashMap<String,SoftReference<Bitmap>>(); package com.itguigu; import java.lang.ref.WeakReference; /** * 弱引用:只要垃圾回收到来,就会被回收 */ public class WeakReferenceDemo { public static void main(String[] args) { Object o1 = new Object(); WeakReference<Object> weakReference = new WeakReference<>(o1); System.out.println(o1); System.out.println(weakReference.get()); o1 = null; System.gc(); System.out.println("============="); System.out.println(o1);//null System.out.println(weakReference.get());//null } }

​ 谈谈WeakHashMap的使用?—>可以做高速缓存

package com.itguigu; import java.util.HashMap; import java.util.WeakHashMap; /** * WeakHashMap */ public class WeakHashMapDemo { public static void main(String[] args) { myHashMap(); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); myWeakHashMap(); } private static void myWeakHashMap() { WeakHashMap<Integer,String> map = new WeakHashMap<>(); Integer key = new Integer(2); String value = "HashMap"; map.put(key,value); System.out.println(map);//{2=HashMap} key = null; System.out.println(map);//{2=HashMap} System.gc(); System.out.println(map);//{}弱引用,被回收 } private static void myHashMap() { HashMap<Integer,String> map = new HashMap<>(); Integer key = new Integer(1); String value = "HashMap"; map.put(key,value); System.out.println(map);//{1=HashMap} key = null; System.gc(); System.out.println(map);//{1=HashMap}默认是强引用,map还是map } } 虚引用:幽灵引用(任何时候都可能被回收) 必须和引用队列(ReferenceQueue)联合使用 只要用于跟踪对象被垃圾回收的状态。 package com.itguigu; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.WeakHashMap; /** * WeakHashMap */ public class ReferenceQueuDemo { public static void main(String[] args) throws InterruptedException { Object o1 = new Object(); ReferenceQueue<Object> referenceQueue = new ReferenceQueue(); WeakReference<Object> weakReference = new WeakReference<>(o1,referenceQueue); System.out.println(o1);//java.lang.Object@3f99bd52 System.out.println(weakReference.get());//java.lang.Object@3f99bd52 System.out.println(referenceQueue.poll());//null System.out.println(">>>>>>>>>>>>>>>>>>>>>"); o1 = null; System.gc(); Thread.sleep(500); System.out.println(o1);//null System.out.println(weakReference.get());//null System.out.println(referenceQueue.poll());//java.lang.ref.WeakReference@4f023edb 回收之前被放在了引用队列 } } ----------------|StackOverflowError: //java.lang.StackOverflowError public class StackOverflowErrorDemo { public static void main(String[] args) { myStackOverflow(); } private static void myStackOverflow() { myStackOverflow(); } }

---------------|OutOfMemoryError: package com.itguigu; import java.util.Random; /** * -Xms10m -Xmx10m * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space */ public class JavaHeapSpaceDemo { public static void main(String[] args) { String str = "atguigu"; while (true){ str += str + new Random().nextInt(1111111) + new Random().nextInt(22222222); str.intern(); } } } ----------------|OutofMemoryError ----------------|

4、GC垃圾回收算法和垃圾收集器的关系?分别是什么?

​ GC算法(引用计数/复制/标清/标整)是内存回收的方法论,垃圾收集器就是对算法的落地实现

4种垃圾回收算法思想----4种垃圾收集器 目前还没有完美的收集器出现,更没有万能的收集器,只是针对具体应用最合适的收集器,进行分代收集。 4种垃圾收集器: Serial(串行回收):为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有的用户线程,所以不适合服务器环境。 parallel(并行回收):多个垃圾收集线程并行工作,用户线程暂停,适用于科学计算/大数据处理首台处理等弱交互。 CMS(并发标记清除):用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程,互联网公司多用它,适用对响应时间有要求的场景。 G1:G1垃圾回收期将堆内存分割成不同的区域然后并发的对其进行垃圾回收。 ZGC(java11):

5、怎么查看服务器默认的垃圾收集器是哪个?生产上如何配置垃圾收集器?对垃圾收集器的理解?

查看默认垃圾收集器:java -XX:+PrintCommandLineFlags -version java8默认:-XX:+UseParallelGC(并行垃圾回收) java中的GC回收的类型主要有(7种垃圾回收:UseSerialOldGC已近废弃-相当于引用计数): UseSerialGC、UseParallelGC、UseConcMarkSweepGC(CMS)、UseParNewGC(年轻区)、UseParallelOldGC(老年区)、UseG1GC Young Generation:Serial、ParNew、ParalleScaveng Old Generation:CMS、Serial Old(MSC)、Parallel Old、 G1既用于young也用于old 新生代:串行GC(Serial/Serial Copying)、并行GC(ParNew)、并行回收GC(Parallel/Parallel Scavenge) 老年代:

=======新生代》》》》》》》》只要新生代被配置,老年代会自动被激活 开启串行参数:-XX:+UseSerialGC 开启后会使用:Serial(Young区)+Serial Old(Old区)的收集器组合 表示:新生代、老年代都会使用串行回收收集器,新生代使用复制算法,老年代使用标记整理算法。

开启并行参数:-XX:+UseParNewGC 启用ParNew收集器,只影响新生代的收集,不影响老年代, 开启后悔使用:ParNew(Young区)+Serial Old(Old区)的收集器组合,新生代使用复制算法,老年代使用标记整理算法。 但是ParNew+Tenured的搭配,java8已经不再被推荐 备注:-XX:+UseParNewGC 限制线程数量,默认开启和CPU数目相同的线程数 开启并行回收参数(java8默认):-XX:UseParallelGC或-XX:+UseParallelOldGC(可相互激活) 使用Parallel Scanvenge收集器 开启后:新生代使用复制算法,老年代使用标记-整理算法 注意:-XX:ParallelGCThreads=数字N 表示启动多少个GC线程 cpu>8 N=5/8 cpu<8 N=实际个数 重点: 可控制的吞吐量(Thoughput=运行用户代码时间/(运行代码时间+垃圾回收时间),比如:程序运行99分钟,垃圾回收1分钟,吞吐量就是99%)。高吞吐量意味着高效的利用CPU的时间,它多用于后台运算而不需要太多交互的任务。

=======老年代》》》》》》》》

………… 并发标记清除GC(CMS): 4步:初始标记(CMS initial mark) 并发标记(CMS concurrent mark):和用户线程一起工作 重新标记(CMS remark) 并发清除(CMS concurrent sweep):和用户线程一起工作 优缺点: 优:并发收集低停顿 缺:对cpu资源压力大;采用标记清除算法会导致大量碎片 组合的选择: 1->单CPU或小内存,单机程序 -XX:+UseSerialGC 2->多CPU,需要最大吞吐量,如后台计算型应用 -XX:+UseParallelGC 或者 -XX:UseParallelOldGC 3->多CPU,追求低停顿时间,需要快速响应如互联网应用 -XX:+UseConcMarkSweepGC -XX:+ParNewGC

6、G1垃圾收集器-young和old

以前收集器特点: 年轻代和老年代是各自独立且连续的内存块; 年轻代收集使用单eden+S0+S1进行复制算法; 老年代收集必须扫描整个老年代区域; 都是以尽可能少而快地执行GC为设计原则。 G1特点: 1)G1能充分利用多CPU、多核环境硬件优势,尽量缩短STW; 2)G1整体上采用标记-整理算法,局部通过复制算法,不会产生内存碎片; 3)宏观上G1之中不再区分年轻代和老年代。把内存划分成多个独立的子区域(Region),像棋盘; 4)G1收集器里面将整个的内存区都混合在一起,但本身依然在小范围内要进行年轻代和老年代的区分,保留新生代和老年代,但他们不再是物理隔离的,而是一部分Region的集合且不需要Region是连续的,也就是说依然采用不同的GC方式来处理不同的区域; 5)G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备,G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换。 G1底层原理: Region区域化垃圾收集器:最大的好处-化整为零,避免全内存扫描,只需要按照区域来进行扫描; 常用参数配置(了解): -XX:+UseG1GC -XX:G1HeapRegionSize=n 设置…… G1和CMS的比较 1.G1不会产生内存碎片; 2.是可以精确控制停顿;该收集器是把整个堆(新生代、老年代)划分成多个固定大小的区域,每次根据允许停顿的时间去收集垃圾最多的区域。

7、GitHub

常用词含义: watch:会持续收到该项的动态 fork:复制某个项目到自己的GitHub仓库中 stat:可以理解为点赞 clone:将项目下载至本地 follow:关注你感兴趣的作者,会收到他们的动态 in限制搜索范围: 公式:xxx关键词 in:name或description或readme xxx in:name 项目名包含xxx的 xxx in:description 项目描述包含xxx的 xxx in:readme 项目的readme文件中包含xxx的 组合使用: 搜索项目名或者readme中包含秒杀的项目 seckill in:name,readme,description ----表示项目名、readme文件以及描述中都包含秒杀(seckill)的项目 star按照点赞数查询 forks相当于收藏数 ---在什么之间 springboot starts:>5000 --->点赞数超过5000的springboot项目 springboot forks:100..200 stars:80..100 awesome加强搜索:一般是用来收集学习、工具、书籍类的相关项目 awesome 关键字 高亮显示某一行代码 地址+#L数字(数字表示行号) 地址+#L数字(数字表示行号)-L数字 项目内搜索 在项目内按 t 搜索某个地区内的大佬 location:地区 language:语言 比如:location:beijing language:java
最新回复(0)