我试图将其WeakHashMap
用作Set
弱引用的并发。
this.subscribers =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
当元素进入垃圾收集时,我的集合继续将其报告为收集的一部分。因此,地图似乎正在不断增长。
该文档说:
放弃键后,其条目将有效地从地图中删除,…
但是实际上似乎并非如此。
有没有WeakHashMap
清除碎屑的地方?
是的,WeakHashMap
可以清除碎屑。用于垃圾回收的密钥不再以大小报告。但是您必须等待垃圾收集真正发生。
似乎您对将对象进行垃圾回收的想法不正确。也许您的对象已成为垃圾收集的 候选
对象,但尚未被收集。尝试调用垃圾收集器,等待片刻完成。但是请记住,对的调用System.gc()
只是对JVM的建议,根据您的JVM实现和当前的运行时场景,可能会被忽略。
这是一个完整的示例应用程序。请注意,该Set
报告报告了size
调用Set::remove
还是让对象超出范围的减少。
package com.basilbourque.example;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
public class WeakHashMapExercise {
public static void main ( String[] args ) {
WeakHashMapExercise app = new WeakHashMapExercise();
app.doIt();
}
private void doIt ( ) {
Set < UUID > set =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
UUID uuid1 = UUID.fromString( "a8ee1e34-cead-11e8-a8d5-f2801f1b9fd1" );
UUID uuid2 = UUID.fromString( "39bda2b4-5885-4f56-a900-411a49beebac" );
UUID uuid3 = UUID.fromString( "0b630385-0452-4b96-9238-20cdce37cf55" );
UUID uuid4 = UUID.fromString( "98d2bacf-3f7f-4ea0-9c17-c91f6702322c" );
System.out.println( "Size before adding: " + set.size() );
set.add( uuid1 );
set.add( uuid2 );
set.add( uuid3 );
set.add( uuid4 );
System.out.println( "Size after adding 4 items: " + set.size() ); // Expect 4.
set.remove( uuid3 );
System.out.println( "Size after removing item # 3: " + set.size() ); // Expect 3.
uuid2 = null; // Release that UUID to garbage-collection.
// That released object may still appear in our `Set` until garbage collection actually executes.
System.gc(); // Ask the JVM to run the garbage-collection. Only a suggestion, may be ignored.
try {
Thread.sleep( 1_000 ); // Wait a moment, just for the heck of it.
} catch ( InterruptedException e ) {
e.printStackTrace();
}
System.out.println( "Size after making garbage of item # 2: " + set.size() ); // Expect 2.
for ( UUID uuid : set ) {
System.out.println( uuid.toString() );
}
}
}
看到此代码在IdeOne.com上实时运行。
添加前大小:0
添加4个项目后的大小:4
移除项目3后的尺寸:3
制作项目#2的垃圾后的尺寸:2
在我的情况下,使用Java的10.0.2版本的OpenJDK基础的祖鲁JVM从阿祖尔系统,垃圾收集器似乎在我的请求被激活。如果我将延迟或System.gc
通话延迟一秒钟,那么报告的最后一个大小将保持不变,3
而不是预期的大小2
。
您甚至可以在IdeOne.com上实时运行此代码时看到此行为。请注意,下面的最后一项是,3
但是上面的是2
。
添加前大小:0
添加4个项目后的大小:4
移除项目3后的尺寸:3
制作项目#2的垃圾后的尺寸:3
这是一个内存数据安全问题。 java垃圾收集是否安全地清除垃圾数据? 显然,在一个数据块被垃圾收集后,我不能再检索它了,但黑客还能通过内存转储来检索数据吗?
问题内容: 与同事进行了讨论。当诸如c#或java垃圾之类的语言收集诸如字符串之类的对象并将其返回到堆时,它们是否也清除了该内存块,例如用0或1覆盖? 我的假设是,除非按原样返回该块,除非使用诸如带有带有finalize重载的securestring之类的类将该块清零。 问题答案: 实际上,不,这不会发生。覆盖刚刚释放的内存需要花费时间,因此会有性能损失。“安全”之类的物体SecureString
问题内容: 我正在使用实现缓存。我想知道是否要遍历此映射的键,同时垃圾回收器正在主动从此映射中删除键,我会收到吗?我不这么认为,因为据我所知,并发修改异常是由于应用程序代码中的错误而发生的,开发人员忘记了同一个映射是由其他线程共享/使用的,因此在这种情况下,应该不会发生。但是想知道当WeakHashMap不同步时JVM将如何处理吗? 问题答案: 正如bkail所说,当GC从a中“删除”一个条目时,
问题内容: 简短形式:CMS垃圾收集器似乎无法收集数量不断增加的垃圾;最终,我们的JVM填满,应用程序变得无响应。通过外部工具(JConsole或)强制GC 清理一次。 更新:该问题似乎与JConsole的JTop插件有关。如果我们不运行JConsole,或者在没有JTop插件的情况下运行它,则该行为消失。 (技术说明:我们正在Linux 2.6.9机器上运行32位Sun JDK 1.6.0_07
主要内容:JEP 189 : Shenandoah:一个低暂停时间的垃圾收集器(实验性),JEP 346 : 及时返回未使用的已提交内存,JEP 344:可中止的混合集合Java 12 为其垃圾收集算法引入了多项增强功能。 JEP 189 : Shenandoah:一个低暂停时间的垃圾收集器(实验性) 引入了一个实验性的低暂停时间垃圾收集器 Shenandoah 以减少 GC 暂停时间。它与运行 Java 线程并行工作。这有助于减少 GC 对堆大小的依赖性并使其保持一致。现在垃圾收集暂停时间对于
问题内容: 什么是JavaScript垃圾回收?为了编写更好的代码,对于Web程序员来说,了解JavaScript垃圾回收有什么重要意义? 问题答案: 从该页面引用: JScript使用了非世代的标记清除垃圾收集器。它是这样的: 每个“范围内”的变量都称为“清除剂”。清道夫可以指数字,对象,字符串等。我们维护一个清道夫列表- 变量进入作用域时将移入scav列表,超出范围时将其移出scav列表。 垃