# java-base **Repository Path**: interview_44/java-base ## Basic Information - **Project Name**: java-base - **Description**: java基础知识梳理,了解 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-02-28 - **Last Updated**: 2024-08-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # java-base #### 介绍 java基础知识梳理,了解 ### 0、java虚拟机 ![](./picture/1、java虚拟机.drawio.png) 五大件:方法区、堆、pc寄存器、本地方法栈、java方法栈。 2中编译方式:解释执行,即时编译。 ### 1、HashMap 基本原理 ![](./picture/1-hashmap.drawio.png) ### 2、ConcurrentHashMap ![](./picture/2-cunrrenthashmap.drawio.png) ### 3、四种对象引用 ![](./picture/3-四种引用.drawio.png) 1、强引用,只要引用在就不会被GC垃圾回收。 2、弱引用,继承WeakReference,只要是弱引用,立马被GC垃圾回收。 ThreadLocal使用的是ThreadLocalMap,对象使用弱引用,key是弱引用,对象存放在堆内存,key被释放之后,value没有被释放,导致内存溢出。 3、虚引用 在GC垃圾回收之后,虚引用对象会移到ReferenceQueue里面。 4、软引用 只要有足够的内存,GC不会回收软引用的对象。 ### 4、垃圾回收器 ![](./picture/5-垃圾回收.drawio.png) 垃圾回收器把内存分为新生代和老年代,一般比例为1:2。 新生代有Eden区和Survival区,一般8:1:1。 新生代MinorGC就是把新生代中Eden区的对象回收,放入survival区。先进入from,后一次进入to,经过多次翻炒,没有被回收,就进入老年代。 老年代fullGC压缩整理内存垃圾,会触发STW卡顿。 ### 5、垃圾回收算法 ![](./picture/6-垃圾清除算法.drawio.png) 1、MinorGC一般新生代使用《标记复制算法》,把垃圾清除,剩余的对象整理好了复制到另外一块内存,既耗时间,又耗空间。 2、FullGC一般使用《标记清除》和《标记整理》。 标记清除:CMS垃圾回收器,一般会出现严重的碎片化。 标记整理:G1,ParOldGc,垃圾回收后把对象往前移,节约内存空间,但是非常耗时,耗时间不耗空间。 G1把老年代划分为多个Region,在回收垃圾事不用全堆进行。 ### 6、JDK8使用的垃圾回收器 ![](./picture/7-java8默认的垃圾回收器.drawio.png) jdk8默认使用Parallel Scavenge + ParOld GC。 可以选择使用CMS,适合大内存场景并且老年代不需要经常GC。 可以使用G1,一般最少使用32G,最大320G,适合大量对象存活的情况。 ### 7、很么时候触发GC YongGC: 1、eden的内存不足,创建新对象会触发MinorGC。 2、设置eden区到一定使用率触发MinorGC。 3、FullGC前会触发MinorGC。 FullGC: 1、YongGC可能会触发FullGC。 2、老年代空间不足会触发FullGC。 3、dump live的内存信息会触发FullGC。 4、创建大对象,eden区内存不足,老年代内存不足,就会触发FullGC。 5、MinorGC之前,会比老年代,是否足够存放eden区的存活对象,如果不足够,就FullGC。 正常10S一次YongGC,FullGC一般要10分钟以上。 ### 8、DirectBytBuffer垃圾回收 ![](./picture/4-DirectBytBuffer回收.drawio.png) 主动回回去扫描Reference的pending list(如果设置了禁用System.gc则无效),调用等待回收的cleaner,进入pending list进行内存回收。 被动回收去扫描Reference的pending list(如果设置了禁用System.gc则无效),调用等待回收的cleaner,进入pending list进行内存回收。 直接内存内存不足,OOM怎么办? 如果不设置MaxDirectMemorySize的话,跟JVM堆内存同样大小。一般堆内存占总内存1/4。 解决办法: 1、配置MaxDirectMemorySize大小,但是Unsafe对此配置无效。 2、使用堆外内存不建议使用jvm的禁用System.gc()这个方法禁用。 ### 9、DirectByteBuffer直接内存使用场景 ![](./picture/9-directByteBuffer.drawio.png) Netty 利端: 1、可以减少从堆外到堆外的拷贝,Netty大量使用堆外内存。 2、堆外内存适合大内存对象,减少FullGC带来的停顿。 3、对于生命周期短的对象,可以使用堆外内存池化,重复利用堆外内存。 4、减少STW,可以使用堆外内存。 弊端: 1、直接内存使用不合理,导致内存泄露。 2、直接内存数据结构是字节数组,结构复杂,要序列化-反序列化。 3、直接内存是虚地址,虚内存,内存不够,(swap操作)会使用交换文件内存,性能更低。 ### 10、java3种文件io 1、Io-java.io包:普通io,FileWritter,FileReader。 2、Nio-java.nio包:FileChannel,文件通道,并不一定非阻塞。 3、Mmap(内存映射IO),把文件映射成虚拟内存,用户针对MapByteBuffer操作用户空间 ### 10、Mmap内存映射 ![](./picture/10-Mmap.drawio.png) rocketMq 把文件内存地址映射到jvm内存的DirectBytBuffer, 用户操作文件读写时就操作BytBuffer流。 像访问普通内存一样。 ### 11、kafka零拷贝 ![](./picture/11-零拷贝.drawio.png) kafka 从一开始的内核态拷贝文件,然后内核修改了套接字缓冲区描述符,直接把文件从socket中写出。 限制只能发文件。