为什么JAVA的垃圾回收机制无法避免内存泄漏

一、本文参考:
1.《深入理解java虚拟机 JVM高级特性与最佳实践》
2.http://coderevisited.com/memory-leaks-in-java/
二、对象已死的判定方法
要进行JVM中对象回收首先要判断对象是否已经死亡,判断的方法有如下几个:
1.引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻 计数器为0的对象就是不可能再被使用的。
但是主流的java虚拟机里面没有选用引用计数器算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。
2.可达性分析算法
这个算法的基本思想就是通过一系列的称为“GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连接时,则证明此对象是不可用的。如下图所示,对象object5、object6、object7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收对象。
三、导致内存泄漏的情况及代码
java 堆内存泄漏。是由于java对象不停创建但是没有释放对象引用导致的。
以下是关于java代码,此代码是引自http://coderevisited.com/memory-leaks-in-java/
类com.code.revisited.memoryleaks.Stack提供了实现栈的一些方法,包括遍历,入栈,出栈等操作。假设原来目的是为了现实使用(当然这里是为了解释内存泄漏)。
package com.code.revisited.memoryleaks;import java.util.Iterator;
import java.util.NoSuchElementException;/*** @author sureshsajja* */
public class Stack<E> implements Iterable<E> {private int N;private E[] array;@SuppressWarnings("unchecked")public Stack(int capacity) {array = (E[]) new Object[capacity];}@Overridepublic Iterator<E> iterator() {return new StackIterator();}private class StackIterator implements Iterator<E> {private int i = N - 1;@Overridepublic boolean hasNext() {return i >= 0;}@Overridepublic E next() {if (!hasNext()) {throw new NoSuchElementException();}return array[i--];}@Overridepublic void remove() {throw new UnsupportedOperationException();}}public void push(E item) {if (isFull()) {throw new RuntimeException("Stack overflow");}array[N++] = item;}public E pop() {if (isEmpty())throw new RuntimeException("Stack underflow");E item = array[--N];return item;}public boolean isEmpty() {return N == 0;}public int size() {return N;}public boolean isFull() {return N == array.length;}public E peek() {if (isEmpty())throw new RuntimeException("Stack underflow");return array[N - 1];}}

类com.code.revisited.memoryleaks.StackTest用于执行栈操作。要进行入栈及出栈10000次操作,理想是入栈时分配堆内存,出栈后对象被回收。

package com.code.revisited.memoryleaks;/*** @author  sureshsajja**/
public class StackTest {/*** @param args*/public static void main(String[] args) {Stack<Integer> s = new Stack<Integer>(10000);for (int i = 0; i < 10000; i++) {s.push(i);}while (!s.isEmpty()) {s.pop();}while (true ) {// do something
              }}}
执行开始。我们使用VisualVM进行观察。为了更明显一些,将栈操作部分代码注释也执行一下。
package com.code.revisited.memoryleaks;/*** @author  sureshsajja**/
public class StackTest {/*** @param args*/public static void main(String[] args) {
//            Stack<Integer> s = new Stack<Integer>(10000);
//            for ( int i = 0; i < 10000; i++) {
//                   s.push(i);
//            }
//
//            while (!s.isEmpty()) {
//                   s.pop();
//            }while (true ) {// do something
              }}}

把栈操作的设为1号,没有栈操作的设置为2号,分别生成Heap Dump文件,我们看一下类实例的截图:

首先是1号截图
首先是2号截图
显然预期的栈操作出栈后并没有释放掉Integer对象的引用(实际上看代码也知道),所以不会被GC回收。真正的实际情况这种引用将会很隐蔽,但是根本总是由于对象仍然被引用。
四、结语
本篇仅对java堆内存泄漏进行了简单说明,下一篇将讨论其他相关的内存泄漏。有不对的地方欢迎拍砖>_<

转载于:https://www.cnblogs.com/bobsha/p/5228335.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/272248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java里try catch的简单用法

Java里try catch的简单用法&#xff1a; Java里try catch的简单用法&#xff1a; 1、trycatch 程序的流程是&#xff1a;运行到try块中&#xff0c;如果有异常抛出&#xff0c;则转到catch块去处理。然后执行catch块后面的语句 扩展部分&#xff1a; 1、trycatchfinally 程序…

【代码笔记】iOS-点击城市中的tableView跳转到旅游景点的tableView,下面会有“显示”更多。...

一&#xff0c;效果图。 二&#xff0c;工程图。 三&#xff0c;代码。 RootViewController.h #import <UIKit/UIKit.h>interface RootViewController : UIViewController <UITableViewDelegate,UITableViewDataSource> {UITableView * _tableView;NSMutableArray …

Android Studio项目结构介绍

新建一个空的工程会出现以下界面&#xff1a; 从上往下依次是&#xff1a;项目名称、包名、项目存储的位置、项目所用的语言、项目所用的Android的系统版本。 进入之后右侧可选择界面的展示结构&#xff1a; 如果选择Android则会出现下面的结构展示&#xff1a;MainActivity是…

对于Ping的过程,你真的了解吗?

作者&#xff1a; 木木匠链接&#xff1a;https://juejin.im/post/5c15ec0f6fb9a049ec6af8b2一、概览对于ping命令&#xff0c;想必只要是程序员都知道吧&#xff1f;当我们检查网络情况的时候&#xff0c;最先使用的命令肯定是ping命令吧&#xff1f;一般我们用ping查看网络情…

Andropid自己定义组件-坐标具体解释

在做一个view背景特效的时候被坐标的各个获取方法搞晕了&#xff0c;几篇抄来抄去的博客也没弄非常清楚。 如今把整个总结一下。 事实上仅仅要把以下这张图看明确就没问题了。 涉及到的方法一共同拥有以下几个&#xff1a; view获取自身坐标&#xff1a;getLeft(),getTop(),get…

一阶段结束考核题(链表的嵌套使用)

链表A&#xff0c;每个节点存放一个新的链表B1&#xff0c;B2,B3,B4,B5的头结点。 场景&#xff1a;一个年级&#xff0c;相当链表A 该年级5个班&#xff0c;每个班5个人&#xff0c;相当于链表B1–B5 做一个学生成绩管理系统 学生成绩有语文 数学 英语 功能&#xff1a; 录入成…

RocketMQ带你快速入门

1. MQ介绍 ##1.1 为什么要用MQ 消息队列是一种“先进先出”的数据结构 转存失败重新上传取消 其应用场景主要包含以下3个方面 应用解耦 系统的耦合性越高&#xff0c;容错性就越低。以电商应用为例&#xff0c;用户创建订单后&#xff0c;如果耦合调用库存系统、物流系统、…

年过35岁的程序员都去哪了?一张图道尽老程序员们的花样出路

有人来&#xff0c;有人去。程序员何其多&#xff0c;想知道他们都去哪了吗?对于程序员的工作出路&#xff0c;小编有以下几点建议&#xff1a;20-27岁&#xff1a;技术积累阶段假设本科22岁毕业&#xff0c;那么工作的前5年对你来说是打基础的阶段。在这5年时间里面&#xff…

em,rem

em rem 相对单位: 也可用于设置padding line-height等em相对当前容器的默认字体设置比如,所有浏览器默认字体都是16px,body{ font-size:62.5%}以后即1em10px; 1.2em12px 在线转换tool: http://pxtoem.com/em(css2.0) rem(css3.0)rem相对于页根元素的字体大小&#xff0c;即 ht…

分布式、高并发、多线程,到底有什么区别?

当提起这三个词的时候&#xff0c;是不是很多人都认为分布式高并发多线程&#xff1f;当面试官问到高并发系统可以采用哪些手段来解决&#xff0c;或者被问到分布式系统如何解决一致性的问题&#xff0c;是不是一脸懵逼&#xff1f;确实&#xff0c;在一开始接触的时候&#xf…

linux文件编程(open、write、read、creat、lseek函数)

文件编程内容比较多&#xff0c;如文件系统原理及访问机制文件在内核中的管理机制&#xff0c;什么是文件信息节点iNode、文件共享、文件权限、各种用户对其权限等等。以下主要记录如何用代码操作文件&#xff0c;实现文件的创建、打开、编辑等自动化执行。 文件描述符介绍、其…

记忆化搜索,FatMouse and Cheese

题目链接&#xff1a;http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode1107 http://acm.hdu.edu.cn/showproblem.php?pid1078 1、从gird[0][0]出发&#xff0c;每次的方向搜索一下&#xff0c;每次步数搜索一下 for(i0; i<4; i) {for(j1; j<k; j){int tx…

九种跨域方式实现原理(完整版)

前言前后端数据交互经常会碰到请求跨域&#xff0c;什么是跨域&#xff0c;以及有哪几种跨域方式&#xff0c;这是本文要探讨的内容。一、什么是跨域&#xff1f;1.什么是同源策略及其限制内容&#xff1f;同源策略是一种约定&#xff0c;它是浏览器最核心也最基本的安全功能&a…

文件编程练习

自己实现linux CP指令 实现cp指令的思路&#xff1a; 打开要复制的原文件读原文件的内容到buf打开或者创建要粘贴的文件将buf里面的内容写到目标文件关闭两个文件 main 函数的标准原型&#xff1a; main 函数的标准原型应该是 int main(int argc, char *argv[]);argc 是命令…

java.lang.OutOfMemoryError: GC overhead limit exceeded

今天现场weblogic报java.lang.OutOfMemoryError: GC overhead limit exceeded&#xff0c;在metalink查了下&#xff0c;有明白解释&#xff0c;要设置一个JVM參数。只是因为当前weblogic内存设置为4G&#xff0c;所以设置參数的做法事实上并非解决这个问题之道。还是要分析web…

[翻译] Visual Studio 2019 RC版发布

今天&#xff0c;我们将分享 Visual Studio 2019 的发布候选版(RC 版) - 这是在 4 月 2 日的虚拟发布活动上正式发布之前的最后步骤之一。 您可以在 visualstudio.com/downloads 下载 RC 版。与往常一样&#xff0c;查看RC 版的发行说明以获取更多详细信息。发布候选版的说明在…

fread、fwrite、fopen函数的简单使用和open、read、write区别解析

这几个函数的区别&#xff1a;fread、fwrite、fopen和open、read、write区别解析 标准C库函数的简单使用 fopen函数原型&#xff1a; #include <stdio.h> FILE *fopen(const char *pathname, const char *mode);第一个参数是&#xff1a;要打开的文件路径 第二个参数是…

docker安装rocketmq你学会了吗

防火墙开通端口 9876 10911 9800 firewall-cmd --zonepublic --add-port9876/tcp --permanent firewall-cmd --zonepublic --add-port10911/tcp --permanent firewall-cmd --zonepublic --add-port9800/tcp --permanent firewall-cmd --reload 创建存储文件夹 mkdir -p /root…