1️⃣ Java JVM 相关文章
-
内存结构 🧠
- 深入探讨Java虚拟机的内部存储结构和其组件。
-
JVM运行时内存 💾
- 详细解释Java虚拟机在运行时如何管理和分配内存。
-
垃圾回收与算法 🗑️
- 探索Java虚拟机如何进行垃圾回收以及所使用的算法。
-
IO 💽
- 了解Java虚拟机如何处理输入/输出操作。
2️⃣ Hotspot JVM后台运行的系统线程
3️⃣ 内存区域
4️⃣ Java的引用类型
Java管理对象与内存之间关系的四种引用类型:强引用、软引用、弱引用、虚引用。
💪 1. 强引用
- 定义:简单地为变量分配一个对象就是强引用。
A a = new A();
- 特点:
- 当内存不足时,Java的JVM宁愿抛出
OutOfMemoryError
,也不会回收具有强引用的对象。 - 只有当它们不能通过任何强引用链被访问时,对象才会被收集。
- 若要中断或回收强引用的对象,可以显式地将引用赋值为null,这样JVM会在适当的时候进行垃圾回收。
- 当内存不足时,Java的JVM宁愿抛出
🌫️ 2. 软引用
- 定义:内存足够时不回收,内存不足时才回收,适合做缓存。
SoftReference a = new SoftReference(new A());
- 特点:
- 系统内存充足时不会被回收,即使发生了GC。
- 软引用自身不会被垃圾回收,因为GC Root仍然引用它,所以需要与引用队列配合使用。
- 适合用于缓存场景,当内存不足时,对象会被回收。
🍃 3. 弱引用
- 定义:只要发生GC,就会被回收。
WeakReference a = new WeakReference(new A());
- 特点:
- 只有弱引用指向该对象时,只要发生GC,该对象就会被回收。
- 如果存在强引用与之同时关联,则进行GC时也不会回收该对象。
- ThreadLocal和WeakHashMap内部都使用了弱引用。
👻 4. 虚引用
- 定义:为对象设置虚引用的唯一目的是在对象被GC时接收到系统通知。
PhantomReference a = new PhantomReference(new A(), referenceQueue);
- 特点:
- 无法通过虚引用获取对象实例。
- 必须与引用队列配合使用,当虚引用的对象被回收时,由Reference Handler线程将虚引用对象加入队列。
🛠️ 5. 使用SoftReference实现缓存
SoftReference 是一种强引用,它所保存的对象实例在JVM即将产生 OutOfMemory
时才会被GC回收。这个特性使其非常适合用于设计对象缓存。对于缓存,我们期望被缓存的对象始终常驻内存。但当JVM内存吃紧,为了避免 OutOfMemoryError
导致系统崩溃,我们允许JVM在必要时回收缓存的内存,并在稍后适当的时机将数据重新加载到缓存中。这样的设计使系统更具弹性。
🔹 实例:在内存有限的环境中使用软引用
在内存受限的设备,如Android系统,软引用特别有用。
考虑一个Android应用的场景:应用需要通过网络下载图片。为了提高性能和节省数据流量,我们可以将已下载的图片缓存到内存中。当用户再次访问该图片时,可以直接从缓存中获取,如果缓存中没有,再从网络下载。
在Android中,例如一个ListView可能需要显示一个图片和一些文本描述。图片需要从网络下载、解析并渲染到内存,这是一个非常消耗内存的过程。
问题:
- 如果每次都从硬盘读取图片,会严重影响性能。
- 如果一次性将所有图片加载到内存,可能会导致内存溢出。
软引用可以解决上述问题。
🔹 设计思路
使用一个HashMap
来保存图片的路径和与图片对象关联的软引用之间的映射。当内存不足时,JVM会自动回收这些缓存的图片对象,从而有效地避免了OOM的问题。
📝 6. 引用总结
- 强引用是我们在编码中经常使用的。
- 软引用和弱引用使用得最多,它们描述的是非必须对象。
- 引用级别从高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用。