Joshua Bloch曾经评论过线程本地用法: 线程池的草率使用与线程局部变量的草率使用可能会导致意外的对象保留,正如在许多地方所指出的那样。但把责任推到线程本地上是没有道理的。 threadlocal导致内存泄漏 一旦保持线程不再活动, threadlocal 就应该被垃圾回收。但是当 threadlocal 与现代应用服务器一起使用时,问题就出现了。 现代应用服务器使用一个线程池来处理请求,而不是创建新的请求(例如apache tomcat中的 Executor )。此外,它们还使用单独的类加载器。 由于应用程序服务器中的线程池遵循线程重用的概念,因此它们永远不会被垃圾回收,而是被重用以服务于另一个请求。 现在,如果任何类创建了一个 ThreadLocal 变量,但没有显式地删除它,那么即使在web应用程序停止之后,该对象的副本也将保留在工作线程中,从而防止对象被垃圾回收。 如何预防? removeThreadLocals.set(null) try { threadLocal.set(System.nanoTime); //... further processing}finally { threadLocal.remove;} 解决内存泄漏的其他方法 虽然在处理内存泄漏时没有一刀切的解决方案,但是我们可以通过一些方法将这些泄漏最小化。 启用分析 Java探查器是监视和诊断应用程序内存泄漏的工具。它们分析应用程序内部发生的事情—例如,如何分配内存。 使用探查器,我们可以比较不同的方法,并找到可以最佳利用资源的领域。 在本教程我们一直在使用javavisualvm。请查看我们的Java探查器指南,了解不同类型的探查器,如任务控制、JProfiler、YourKit、Java VisualVM和Netbeans探查器。 详细的垃圾收集 通过启用详细的垃圾收集,我们可以跟踪GC的详细跟踪。要实现这一点,我们需要在JVM配置中添加以下内容: -verbose:gc 通过添加此参数,我们可以看到GC内部发生的详细情况: 使用引用对象以避免内存泄漏 我们还可以使用Java中内置的引用对象 java.lang.ref 处理内存泄漏的包。使用 java.lang.ref 包,而不是直接引用对象,我们使用对对象的特殊引用,以便于对它们进行垃圾回收。 引用队列旨在让我们知道垃圾回收器执行的操作。 Eclipse内存泄漏警告 对于jdk1.5及更高版本的项目,每当遇到明显的内存泄漏情况时,Eclipse都会显示警告和错误。因此,在Eclipse中开发时,我们可以定期访问“Problems”选项卡,并对内存泄漏警告(如果有)保持警惕: Benchmarking基准测试 我们可以通过执行基准测试来测量和分析Java代码的性能。这样,我们就可以比较不同方法的性能来完成相同的任务。这可以帮助我们选择更好的方法,也可以帮助我们保存记忆。 有关基准测试的更多信息,请访问我们的Java微基准标记教程。 代码评审 最后,我们总是采用经典的、老派的方法来完成简单的代码遍历。 在某些情况下,即使是这种看起来微不足道的方法也有助于消除一些常见的内存泄漏问题。 结论 通俗地说,我们可以认为内存泄漏是一种通过阻塞重要内存资源而降低应用程序性能的疾病。而且,与所有其他疾病一样,如果得不到治愈,随着时间的推移,它会导致致命的应用程序崩溃。 内存泄漏很难解决,找到它们需要对Java语言进行复杂的掌握。在处理内存泄漏时,没有一刀切的解决方案,因为泄漏可以通过各种各样的事件发生。 但是,如果我们求助于最佳实践并定期执行严格的代码遍历和分析,那么我们就可以将应用程序中内存泄漏的风险降到最低。 原文链接: http://javakk.com/911.html 原文链接: http://javakk.com/911.html 如果觉得本文对你有帮助,可以转发关注支持一下