根据番石榴的文档MapMaker.softValues():
警告:在大多数情况下,最好设置每缓存最大大小而不是使用软引用.如果您熟悉软引用的实际后果,则应该只使用此方法.
我对软引用有一个中间的理解 - 它们的行为,用途以及它们与垃圾收集的契约.但是我想知道这些实际后果是由博士提到的.为什么使用最大尺寸而不是软参考更好?在实现缓存方面,软引用的算法和行为是否使得它们的使用比硬编码上限更有效?
我正在尝试通过这篇“Java 中的软引用”文章来研究软引用的含义:
https://www.baeldung.com/java-soft-references
我理解这篇文章的问题是它通过术语“软可达对象”定义了术语“软引用”,但我不知道“软可达对象”是什么意思。
也就是说,堆中的对象要么有对它的引用,要么没有,对吗?
引用要么指向有效对象,要么为空,对吗?
什么时候对象变得“软可及”?
还是我弄错了?
在创建如此多的强引用时会出现OOM错误,因为GC不会收集强引用,但如果没有额外的内存,GC将收集弱引用.所以我的问题是:我设置一个循环来创建弱参考-Xmx2M
Set<SoftReference<Integer>> sa = new HashSet<~>();
for (int i = 0; i < size; i++) {
SoftReference<Integer> ref = new SoftReference<Integer>(i);
sa.add(ref);
}
Run Code Online (Sandbox Code Playgroud)
它仍然发生在OOM,为什么?
我有一个需要打开多个JFrame的应用程序(它是一个日志查看器,有时您需要在单独的窗口中查看一堆日志来进行比较).
似乎JVM(OS X上的Java 8更新101)持有对JFrame的强引用,这阻止了它被垃圾收集,并最终导致抛出OutOfMemoryError.
若要查看该问题,请运行此问题,最大堆大小为200 MB.每次打开一个窗口时,它都会消耗50兆字节的RAM.打开三个窗口(使用150兆字节的RAM).然后关闭三个窗口(调用dispose),这将释放内存.然后尝试打开第四个窗口.抛出OutOfMemoryError,第四个窗口无法打开.
我已经看到了其他答案,说明在必要时会自动释放内存以避免耗尽,但这似乎并没有发生.
package com.prosc.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
public class WindowLeakTest {
public static void main(String[] args) {
EventQueue.invokeLater( new Runnable() {
public void run() {
JFrame launcherWindow = new JFrame( "Launcher window" );
JButton launcherButton = new JButton( "Open new JFrame" );
launcherButton.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
JFrame subFrame = new JFrame( "Sub frame" ) {
private byte[] bigMemoryChunk = new byte[ …Run Code Online (Sandbox Code Playgroud) 假设我有一个名为"master"的对象,它拥有100个对象,分别称为"slave0"到"slave99".(这不是一个数组.我的"master"类中有100个字段分别叫做salve0到slave99.)现在,假设我的程序首先读入一个包含序列化存储版本的"主"对象的文件.但是,假设我的程序从不使用slave50到slave99的对象.会发生什么?(我的猜测是java程序将首先读取所有100个从属对象作为读取/反序列化过程的一部分,并且只有在读取了所有100个从属对象之后,它才可能选择执行GC,此时对象slave50到slave99将被GC删除并回收内存.这是正确的吗?注意:对象"master"仍然在使用,所以从技术上讲,对象slave50到slave99仍然被父对象,master引用,而父对象master仍然是积极使用.)
所以,让我说我的猜测在GC的运作方式上是正确的; 如果我长时间运行的程序花费几分钟处理对象slave0到slave50,然后进入另一个名为"X"的最终(长时间运行)过程,该过程只处理slave0到slave25的对象,那么会发生什么.然后GC会意识到即使对象slave25到slave50仍然被父对象主机引用,即使仍然使用对象主机,GC仍然足够聪明,可以通过slave50摆脱slave25,因为没有人是否会从"程序X"开始使用它?
即使它有引用(c#或Java),我如何删除对象?
例如:
void Main()
{
var f = new Foo();
var person = f.GetPerson();
}
public class Foo
{
private object _person;
public Foo()
{
_person = new object();
}
public object GetPerson()
{
return _person;
}
}
Run Code Online (Sandbox Code Playgroud)
我想从内存中删除_person我该怎么办?