JVM(4)

55 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第27天,点击查看活动详情

5.7 StringTable垃圾回收

StringTable会进行垃圾回收

5.8 StringTable性能调优

  • 调整 -XX:StringTableSize=桶个数

    • 使用image-20221114220522088即可调整桶个数
  • 考虑将字符串对象是否入池

6.直接内存

6.1 定义

Direct Memory

  • 常见于 NIO 操作时,用于数据缓冲区
  • 分配回收成本较高,但读写性能高
  • 不受 JVM 内存回收管理
  • 直接内存也会导致内存溢出

由图中可以看出,Java在进行读取操作时,需要在2块缓存区的地方进行操作,会使得效率不高

使用直接内存之后,在这块直接内存中,Java代码可以直接访问

6.2 分配和回收原理

  • 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法
  • ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦 ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调 用 freeMemory 来释放直接内存

JVM通过添加-XX:+DisableExplicitGC显式地禁用System.gc(),这样会导致直接内存无法通过调用System.gc来进行垃圾回收

解决方案:

直接使用unsafe进行调用

垃圾回收

  1. 如何判断对象可以回收
  2. 垃圾回收算法
  3. 分代垃圾回收
  4. 垃圾回收器
  5. 垃圾回收调优

1.如何判断对象可以回收

1.1 引用计数法

引用计数法就是一个对象被另一个对象所引用,那么就令这个对象的计数变为1

引用计数法在出现下面这种循环引用时会失效,当这2个对象都无法再使用了,但是2个对象的计数都为1,因此无法进行回收

1.2 可达性分析算法

GC Root(根对象):不能被当做垃圾回收的对象,也就是说,跟GC Root有关系的对象都不能被当作垃圾回收

JVM采用的算法

  • Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
  • 扫描堆中的对象,看是否能够沿着 GC Root对象 为起点的引用链找到该对象,找不到,表示可以回收
  • 哪些对象可以作为 GC Root ?