原标题:面试官:小伙子先来说一下可能引起Java内存泄露的场景吧

本文分析一下可能引起java内存泄露的场景:

通过 finalize 方法

终结器finalizers的使用是潜在内存泄漏问题的另一个来源。每当类的finalize方法被重写时,该类的对象不会立即被垃圾回收。相反,GC将它们排队等待最后确定,这将在稍后的时间点发生。

另外,如果我们的应用程序不能更快地完成或最终处理一个错误,那么如果我们的应用程序不能更快地完成一个错误,那么我们的应用程序就不能完成。

为了证明这一点,让我们考虑一下,我们已经为一个类重写了finalize方法,并且该方法需要一点时间来执行。当此类的大量对象被垃圾回收时,在VisualVM中,它看起来像:

但是,如果我们只删除重写的finalize方法,则同一个程序会给出以下响应:

如何预防?

我们应该避免使用终结器

内部字符串

当Java 7从PermGen转移到HeapSpace时,Java字符串池经历了一次重大变化。但是对于在版本6及以下运行的应用程序,我们在处理大字符串时应该更加注意。

如果我们读取一个巨大的字符串对象,并在该对象上调用intern,那么它将进入字符串池,该池位于PermGen(永久内存)中,只要我们的应用程序运行,它就会一直留在那里。这会阻塞内存并在我们的应用程序中造成内存泄漏。

JVM 1.6中这个例子的PermGen在VisualVM中如下所示:

与此相反,在一个方法中,如果我们只是从文件中读取一个字符串,而不是对其进行内接,那么PermGen看起来像:

如何预防?

解决这个问题最简单的方法是升级到最新的Java版本,因为从JavaVersion7开始,字符串池被移到HeapSpace

如果要处理大型字符串,请增大PermGen空间的大小,以避免任何潜在的OutOfMemoryError:-XX:MaxPermSize=512m

使用ThreadLocals

ThreadLocal是一种构造,它使我们能够将状态隔离到特定线程,从而允许我们实现线程安全。

当使用这个结构时,每个线程都将持有一个对其ThreadLocal变量副本的隐式引用,并将维护自己的副本,而不是在多个线程之间共享资源,只要线程是活动的。

尽管ThreadLocal变量有很多优点,但是它的使用还是有争议的,因为如果使用不当,它们会导致内存泄漏。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

如果觉得本文对你有帮助,可以转发关注支持一下返回搜狐,查看更多

责任编辑:

java线程泄露_面试官:小伙子先来说一下可能引起Java内存泄露的场景吧相关推荐

  1. java 线程状态_面试官问:为什么Java线程没有Running状态?我懵了

    点击上方"占小狼的博客",选择"设为星标" 本文阅读时间大约4分钟. 来源:https://dwz.cn/dLRLBZab Java虚拟机层面所暴露给我们的状态 ...

  2. main线程 子线程 顺序_面试官:线程池如何按照core、max、queue的执行顺序去执行?详解...

    前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...

  3. 面试java你最擅长什么_面试官最喜欢问的10道Java面试题

    1.Java的HashMap是如何工作的? HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 g ...

  4. java semaphore(0)_面试官:说说Java中的信号量?Semaphore

    Semaphore (信号量)是由计算机科学家Dijkstra在1965年提出的,广泛应用不同的操作系统,在管程提出之前信号量就是并发编程领域的霸主!几乎所有并发的语言都支持信号量机制. Semaph ...

  5. 启动rrt什么意思_面试官:你来说一下springboot启动时的一个自动装配过程吧!...

    前言 继续总结吧,没有面试就继续夯实自己的基础,前阵子的在面试过程中遇到的各种问题陆陆续续都会总结出来分享给大家,这次要说的也是面试中被问到的一个高频的问题,我当时其实没答好,因为很早之前是看过spr ...

  6. java数组搞笑_面试官:小伙子,给我说一下Java 数组吧

    Java 数组 Java 语言中提供的数组是用来存储固定大小的同类型元素. 1.声明数组变量 首先必须声明数组变量,才能在程序中使用数组. dataType[] arrayRefVar; // 首选的 ...

  7. jstack 线程状态分析_面试官:说说你是怎么用JDK监控和故障处理工具的吧?例如jstack...

    当JVM发生故障的时候,能应用JDK命令行工具对JVM进行监控和故障诊断是Java开发人员必备的技能之一.本篇文章将为大家带来JVM进行监控和故障诊断常用的命令行工具,如下图: 其中jps.jstat ...

  8. java类加载过程_面试官:java类的加载过程

    Java 类加载机制 类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段. 其中类加载过程包括加载.验证.准备.解析和初始化五个阶段. 类的加载 ...

  9. java分页查询_面试官:数据量很大,分页查询很慢,有什么优化方案?

    准备工作 一般分页查询 使用子查询优化 使用 id 限定优化 使用临时表优化 关于数据表的id说明 <Java 2019 超神之路> <Dubbo 实现原理与源码解析 -- 精品合集 ...

最新文章

  1. centos设置网络自动启动
  2. Logparser 分析 Exchange 日志文件
  3. 深入理解SQL注入绕过WAF和过滤机制
  4. Python中的排序sorted(d.items(), key=lambda x: x[1])
  5. Boost智能指针——shared_ptr
  6. 【arduino】ESP8266播放音乐,ESP8266Audio初试体验测试报告
  7. windows 从端口找应用
  8. SoJpt Boot 2.2-3.8 发布,Spring Boot 使用 Jfinal 特性极速开发
  9. openjdk17体验
  10. 今天maven install时碰到的两个问题(堆溢出和编译错误)
  11. 动态规划(DP)——通俗易懂!
  12. jni直接转byte_JNI jbyteArray转char*
  13. 7 Object类型
  14. Win10任务栏无响应解决方法集锦
  15. html引入微软雅黑,求让所有浏览器支持微软雅黑的方法_html/css_WEB-ITnose
  16. 惠普omen测试软件,性能测试:高品质体验主流游戏
  17. Date对象在Safari与IOS中的“大坑”
  18. stm32正常运行流程图_stm32初始化流程图解析
  19. JSTree的基本用法
  20. 去除下拉框上向下的箭头

热门文章

  1. Python慢,为啥还有大公司用?
  2. 源 arm_arm和X86处理器性能简单测试
  3. 用ssh远程登录服务器时,怎么直接以root用户登录?(需要修改配置,如果不想修改,可以先用普通用户登录再su切换到root用户)
  4. CUDA和cuDNN到底是啥关系?(cuDNN是基于CUDA的深度学习GPU加速库)
  5. Python学习笔记(基础知识点一)
  6. UR驱动包安装过程及遇到问题的解决方案
  7. WireConnection 最小生成树,prim 第九届“图灵杯”NEUQ-ACM程序设计竞赛个人赛
  8. asn1 pem pfx格式证书_Springboot中详细配置SSL证书
  9. 四种保留小数后两位输出方法
  10. java实现系统多级文件夹复制