如何删除Java Logger

时间:2015-11-18 10:04:18

标签: java logging memory-leaks

我在应用程序中发生内存泄漏,该应用程序创建了许多 java.util.logging.Logger 对象,我能够将问题归结为:

import java.util.logging.Logger;

public class LoggerTest
{
    public static void main(String[] args) throws Exception
    {
        new LoggerTest().createManyLoggers();
    }

    public void createManyLoggers() throws Exception
    {
        System.out.println(generateMemoryStatus("before"));

        for (int i = 0; i < 100000; i++)
        {
            Logger.getLogger(LoggerTest.class.getName() + "." + i);
        }

        System.out.println(generateMemoryStatus("after"));

        Thread.sleep(10000L);

        System.out.println(generateMemoryStatus("after cool off"));
    }

    private String generateMemoryStatus(String label)
    {
        System.gc();

        Runtime runtime = Runtime.getRuntime();

        long total = runtime.totalMemory();
        long free = runtime.freeMemory();
        long used = total - free;

        return String.format("used memory: %,10d bytes  %s", used, label);
    }
}

java.util.logging.Logger 的javadoc指出: 重要的是要注意,如果没有保留对Logger的强引用,则可以随时对其中一个getLogger工厂方法返回的Logger进行垃圾收集。

但Logger不是垃圾收集并导致内存泄漏 - 上述代码的输出通常如下所示:

# java -version

java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)

# java -jar loggerTest.jar

    used memory:  1.662.336 bytes  before
    used memory: 25.482.576 bytes  after
    used memory: 25.482.744 bytes  after cool off

即。它吃了超过20MB的内存(也在eclipse中尝试过)。 在实际的应用程序中,父记录器和所有处理程序都从记录器中删除,但由于这没有任何区别,我在这里省略了。

调用

LogManager.getLogManager().reset();

无济于事。因此,我将为我的应用程序创建一个记录器池并重用记录器。

我的问题是:有没有办法真正删除 java.util.logging.Logger 对象,即从内存中删除它们?

1 个答案:

答案 0 :(得分:3)

您无法强制JVM从内存中删除对象。

System.gc()的调用不保证垃圾收集器运行。如果JVM认为它有足够的内存,则可能会忽略对System.gc()的调用。

你能详细说明你的内存泄漏吗?我的意思是在现代硬件和使用JVM,一些对象消耗25Mb不是我所谓的内存泄漏。

运行应用程序时是否存在具体的内存问题,例如OutOfMemoryError

您不一定需要对对象进行池化,JVM会在需要时将其从内存中删除。如果您只想查看其中的操作,只需使用较小的堆(例如-Xmx15m)运行。但这不是一个好主意。除非遇到问题,否则不应考虑调整内存,例如OutOfMemoryError