java - 如何删除 Java 记录器

标签 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 可能随时被垃圾回收。

但 Loggers 没有被垃圾收集并导致内存泄漏 - 上面代码的输出通常如下所示:

# 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 对象,即将它们从内存中删除?

最佳答案

您不能强制 JVM 从内存中删除对象。

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

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

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

您不一定需要将对象放入池中,JVM 会在需要时将它们从内存中移除。如果您只是想看看它的实际效果,只需使用较小的堆运行(例如 -Xmx15m)。但这不是一个好主意。除非遇到问题,例如 OutOfMemoryError,否则不应考虑调整内存。

关于java - 如何删除 Java 记录器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33777006/

相关文章:

azure - 在 azure 应用程序洞察中,记录长 JSON 会被修剪

c++ - 重载运算符中的内存泄漏 =

c++ - std::list 中动态分配的数组导致内存泄漏

java - 了解 Java 堆转储

python - python logging.handlers.RotatingFileHandler 是否允许创建组可写日志文件?

php - 基于日期的 Laravel 日志文件

java - 即使在将适配器设置为布局管理器之后,我也面临着 RecyclerView 没有附加适配器的问题。我一个

java - 创建一个简单的 GridLayout 不起作用

java - 在 <code> 标签内用 <br/> 替换换行符,用 替换空格

java - 单击选定的复选框