我正在学习有关内存泄漏的更多信息,并尝试使用以下代码:
我有下面的代码抛出Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
import com.learn.general.memoryleaks.LeakFactory.Leak;
public class InnerClassMemoryLeakTest {
static Leak[] leaks = new Leak[100000];
public static void main(String[] args) {
while(true) {
for (int i = 0; i < leaks.length; i++) {
leaks[i] = new LeakFactory().getLeak();
}
}
}
private static void createLeak() {
while(true) {
for (int i = 0; i < leaks.length; i++) {
leaks[i] = new LeakFactory().getLeak();
}
}
}
}
import java.util.Calendar;
public class LeakFactory {
double d = Math.random();
Calendar calendar = Calendar.getInstance();
public Leak getLeak(){
return new Leak();
}
public class Leak{
double d_i = Math.random();
Calendar calendar_i = Calendar.getInstance();
}
}
然后我有下面的代码抛出Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class ArrayListMemoryLeak {
public static void main(String[] args) {
List<Object> calendars = new ArrayList<>();
int count = 0;
while(true){
calendars.add(Calendar.getInstance());
}
}
}
问题:第一种情况下的错误是否表明存在内存泄漏,而第二种情况下的错误却没有?
答案 0 :(得分:1)
内存泄漏是程序员无意中保持内存的时间超过了应有的时间,这种无意中的内存使用缓慢,直到没有可分配的内存为止。 >
在Java中,鉴于垃圾回收的性质以及如何看待引用对象的强弱程度,泄漏内存很难解决。
鉴于您必须自己故意 旋转所有这些类,因此没有任何理由要泄漏。您故意这样做。您已经创建了足够的引用,以致耗尽了自己的内存限制。
Java中的内存泄漏通常以一种更狡猾的方式表现出来;某些引用保留在finalize()
方法中,直到类被实际垃圾回收时才释放,并且只有VM知道何时实际发生(永远不会)。 that method is going away Soon™值得庆幸的是,因此使用 that 看到泄漏的可能性至少有所降低。
您也可能不可思议邪恶并做Unsafe
things with the language,但这足以构成危险信号,大多数明智的IDE和工具集都会在这种情况发生之前警告您这种用法。您的手上有大量内存泄漏。
所有这些要说的...不。您看到的异常表明您的内存不足。这不是直接表示内存泄漏。
答案 1 :(得分:0)
根据您的评论:
我正在尝试了解内存泄漏,因此我打算做什么 ....我正在寻找有关这两种情况以及是否首先 case表示内存泄漏而第二种情况不
简单地说,这两个错误都表明JVM内存不足,现在是否由于内存泄漏而导致JVM内存不足是另一回事。
现在,第一种情况-是的,内存泄漏(有意为之),因为内部类持有封闭类的引用,因此使用new LeakFactory()
创建的对象可以使用GC,但不能进行GC因为Leak
内部类对它们有很强的引用。
为更清楚地了解这一点,将public class Leak{
更改为public static class Leak{
,与原始的非静态{{1 }}内部类。
答案 2 :(得分:-1)
太多的对象失去了引用,因此被垃圾回收了。缺省情况下,JVM讨厌98%以上的程序处理专门用于丢弃对象(正在回收内存)。您可以重新调整对象的用途(通过使它们可变并直接将它们重新分配为新用途直接回收自己),也可以通过在命令行中添加-XX:-UseGCOverheadLimit来禁用构成错误的通知。当我自己做几次遗传算法时,我遇到了这个问题。在遗传算法中,很多父母从父母那里创建了许多孩子,然后在下一轮繁殖之前杀死了大多数最不适合的孩子。基本上,即使您实际上没有做错任何事情,您创建的垃圾也比Java所希望的更多。只需在命令行参数中添加-XX:-UseGCOverheadLimit即可查看它是否再次发生。要了解在使用eclipse时将其添加到何处,请遵循以下说明http://www.planetofbits.com/eclipse/increase-jvm-heap-size-in-eclipse/,但请将此行改为-XX:-UseGCOverheadLimit