7

内存泄露的原因

 3 years ago
source link: http://javakk.com/931.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

uAZB7b.png!mobile

在本篇文章中,我们将了解什么是内存泄漏、垃圾收集器、Java中的内存泄漏示例以及检测泄漏的工具。

Java的一个主要优点是内存管理主要由Java虚拟机或更具体的Java垃圾收集器(GC)处理。Java垃圾收集器负责在堆上分配和释放对象。

什么是内存泄漏

在计算机科学中,内存泄漏是指计算机程序不释放不需要的资源而错误地管理内存分配。在Java中,当一个对象不再被应用程序使用,但垃圾回收器无法将其从工作内存(堆)中删除时,就会发生内存泄漏。从长远来看,积累对象而不能删除它们会导致 OutOfMemoryError

为什么对象不被垃圾回收

是否将对象从工作内存中删除取决于对象类型。有两种类型,引用和未引用。GC定期收集未引用的对象,另一方面GC无法收集具有有效引用的对象。

请看下面的图片,以便更好地理解。

JNraAji.png!mobile

另外,在Java中有四种类型的引用可以用来管理GC如何以及何时收集对象。

  • 强引用-这是默认的对象引用。除非引用指向null,否则无法收集具有强引用的对象。
  • 软引用-对象引用使用 java.lang.ref.SoftReference 类不会被收集,即使对象对GC是空闲的。软GC需要清除所有JVM所需的内存。
  • 弱引用-使用java.lang.ref如果JVM检测到没有强引用或软引用链接到任何对象,则将为GC标记. WeakReference 类。
  • 虚引用-对象引用使用 java.lang.ref.PhantomReference 不是由GC自动清理的,需要手动清理。在执行referent的 finalize 方法后,幻影引用被放入引用队列。

什么是垃圾收集器

垃圾收集器是一个JVM守护进程线程,它定期从堆内存收集未引用的对象。当一个对象不再被引用时,它就有资格从堆内存中移出。堆内存分为三个主要区域:年轻一代(Eden空间、S0幸存者空间和S1幸存者空间)、老一代和永久一代。

还有四种类型的垃圾收集器:

  • 串行垃圾收集器
  • 并行垃圾收集器(默认jvm gc)
  • CMS垃圾收集器
  • G1垃圾收集器

垃圾收集器之间的区别:

-XX:+UseSerialGCJVM
-XX:useConMarkSweepGC
XX:+UseG1GCJVM

内存泄漏示例

为了更快地再现内存泄漏,我将使用JVM参数 -Xmx125m 将堆大小降低到125MB

内存泄漏最常见的情况之一是将大量元素集合引用为静态字段。让我们来看一个例子:

private static final List<String> listOfStrings = new ArrayList<>(100000);

public static void main(String[] args) {
    fillStaticList();

    try {
        Thread.sleep(100_000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static void fillStaticList() {
    for (int i = 0; i < 100000; i++) {
        listOfStrings.add("Some large text + " + i);
    }
}

uiiIFve.png!mobile

在JVM进程的生命周期内,GC永远不会收集静态收集。现在,我将在示例中将重集合声明为局部变量:

public static void main(String[] args) {
    fillLocalList();

    try {
        Thread.sleep(100_000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static void fillLocalList() {
    List<String> listOfStrings = new ArrayList<>(100000);
    for (int i = 0; i < 100000; i++) {
        listOfStrings.add("Some large text + " + i);
    }
}

iami2m2.png!mobile

正如您在探查器中所注意到的,一旦方法完成执行,GC就会删除集合。

Java分析器

javaprofiler是一个在JVM级别监视操作的工具。有许多可用的Java分析器,其中最流行的是YourKit、JProfiler和VisualVM。关于VisualVM工具的用法可以参考这篇文章: http://javakk.com/919.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK