在这个主题中,我问了一个有关Java垃圾收集的问题。但是我得到的答案又给了我一个问题。
有人提到垃圾回收器也可以收集类。这是真的?
如果是真的,这是如何工作的?
没有任何引用时,可以对Java中的类进行垃圾回收。在大多数简单的设置中,这永远不会发生,但是在某些情况下可能会发生。
有很多方法可以使类可达,从而阻止其符合GC的资格:
Class
表示类的对象仍然可以访问ClassLoader
这加载的类仍可达ClassLoader
仍然可以加载由加载的其他类如果 没有 那些都是真的,那么ClassLoader
它加载,并且所有的类都是符合GC。
这是一个结构化的示例(充满了不良习惯!),该示例可以证明行为:
GCTester.class
在目录(不是包!)中创建一个字节码文件x
。它的源代码是:
public class GCTester {
public static final GCTester INSTANCE=new GCTester();
private GCTester() {
System.out.println(this + " created");
}
public void finalize() {
System.out.println(this + " finalized");
}
}
然后TestMe
在的父目录中创建一个类x
:
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Field;
public class TestMe {
public static void main(String[] args) throws Exception {
System.out.println("in main");
testGetObject();
System.out.println("Second gc() call (in main)");
System.gc();
Thread.sleep(1000);
System.out.println("End of main");
}
public static void testGetObject() throws Exception {
System.out.println("Creating ClassLoader");
ClassLoader cl = new URLClassLoader(new URL[] {new File("./x").toURI().toURL()});
System.out.println("Loading Class");
Class<?> clazz = cl.loadClass("GCTester");
System.out.println("Getting static field");
Field field = clazz.getField("INSTANCE");
System.out.println("Reading static value");
Object object = field.get(null);
System.out.println("Got value: " + object);
System.out.println("First gc() call");
System.gc();
Thread.sleep(1000);
}
}
运行TestMe
将产生以下(或类似的)输出:
在主要
创建ClassLoader
装载类
获取静态场
读取静态值
创建GCTester @ 1feed786
获得值:GCTester @ 1feed786
第一次gc()调用
第二次gc()调用(主要)
GCTester @ 1feed786最终确定
主端
在倒数第二行中,我们看到GCTester
实例已完成,这仅意味着该类(和ClassLoader
)可以进行垃圾收集。
问题内容: 是什么决定了垃圾收集器何时真正收集?它是在一定时间之后还是在一定数量的内存用完之后发生的吗?还是还有其他因素? 问题答案: 它在确定是时候运行时运行。在世代垃圾收集器中,一种常见的策略是在第0代内存分配失败时运行收集器。也就是说,每次你分配一小块内存(大块通常直接放置在“旧”代中)时,系统都会检查gen-0堆中是否有足够的可用空间,如果没有,则运行GC释放空间以使分配成功。然后将旧数据
问题内容: 据我所知,GC仅在JVM需要更多内存时才使用,但我不确定。所以,请有人提出这个问题的答案。 问题答案: 据我了解,Java的垃圾收集算法非常复杂,而且不那么直接。另外,GC可用的算法还不止这些,可以在VM启动时通过传递给JVM的参数进行选择。 这里有一个有关垃圾收集的常见问题解答:http : //www.oracle.com/technetwork/java/faq-140837.h
问题内容: 我们正在创建多个子类加载器,以将多个子应用程序加载到Java应用程序“容器”中,从而对热部署进行原型设计。当特定类加载器的类路径发生更改时(即,添加,删除,更新了jar),旧的类加载器将被丢弃(未引用),并为jar的新类路径创建新的类加载器。 更新类路径后,触发热部署,我们进行了堆转储。堆转储(使用内存分析器)表明旧的类加载器未在进行垃圾回收。父类加载器中的某些类正在缓存旧的类加载器。
在Java中,当一个对象没有实时引用时,它就有资格进行垃圾回收。对于字符串,情况并非如此,因为字符串将进入字符串池,而JVM将保持对象活动以供重用。这意味着字符串一旦创建就永远不会被垃圾收集?
问题内容: 我对可以控制CMS收集器启动时间的两个参数感到困惑: (默认为70%) (默认情况下超过90%) 这些参数的确切含义是什么?收集器什么时候开始(标记阶段)并收集(清扫阶段)? 问题答案: 决定何时启动CMS(为了使此选项生效,您还必须设置)。是确定世代空间大小的选项。 参见例如… http://java.sun.com/docs/hotspot/gc1.4.2/faq.html 通常无
问题内容: 我是Java新手,对Java中的垃圾收集器感到困惑。它实际上是做什么的,什么时候生效。请描述Java中垃圾收集器的一些属性。 问题答案: 该垃圾收集器是运行在一个程序的Java虚拟机,其摆脱其未使用的Java应用程序了对象。它是自动内存管理的一种形式。 当典型的Java应用程序运行时,它正在创建新的对象,例如和,但是在一段时间之后,这些对象将不再使用。例如,看下面的代码: 在上面的代码