java内存泄漏的代码 java 内存泄漏

如何编写一个java内存泄露程序?自己改一下下面的代码java内存泄漏的代码 , 把堆栈中的元素改成mp3类型的或更大点的东西
4.Java中参数都是传值的 。
对于基本类型 , 大家基本上没有异议,但是对于引用类型我们也不能有异议 。
Java内存泄露情况
JVM回收算法 是很复杂的,我也不知道他们怎么实现的,但是我只知道他们要实现的就是:对于没有被引用的对象是可以回收的 。所以你要造成内存泄露就要做到:
持有对无用对象的引用!
不要以为这个很轻易做到 , 既然无用 , 你怎么还会持有它的引用? 既然你还持有它 , 它怎么会是无用的呢?
以下以堆栈更经典这个经典的例子来剖析 。
Java代码
public class Stack {
private Object[] elements=new Object[10];
private int size = 0;
public void push(Object e){
ensureCapacity();
elements[size] = e;
}
public Object pop(){
if( size == 0)
throw new EmptyStackException();
return elements[--size];
}
private void ensureCapacity(){
if(elements.length == size){
Object[] oldElements = elements;
elements = new Object[2 * elements.length 1];
System.arraycopy(oldElements,0, elements, 0, size);
}
}
}
上面的原理应该很简单,假如堆栈加了10个元素,然后全部弹出来 , 虽然堆栈是空的,没有我们要的东西,但是这是个对象是无法回收的,这个才符合了内存泄露的两个条件:无用,无法回收 。
但是就是存在这样的东西也不一定会导致什么样的后果,假如这个堆栈用的比较少,也就浪费了几个K内存而已,反正我们的内存都上G了,哪里会有什么影响,再说这个东西很快就会被回收的,有什么关系 。下面看两个例子 。
例子1
Java代码
public class Bad{
public static Stack s=Stack();
static{
s.push(new Object());
s.pop(); //这里有一个对象发生内存泄露
s.push(new Object()); //上面的对象可以被回收了,等于是自愈了
}
}
因为是static,就一直存在到程序退出,但是我们也可以看到它有自愈功能 , 就是说假如你的Stack最多有100个对象,那么最多也就只有100个对象无法被回收其实这个应该很轻易理解,Stack内部持有100个引用,最坏的情况就是他们都是无用的 , 因为我们一旦放新的进取 , 以前的引用自然消失java内存泄漏的代码!
例子2
Java代码
public class NotTooBad{
public void doSomething(){
Stack s=new Stack();
s.push(new Object());
//other code
s.pop();//这里同样导致对象无法回收,内存泄露.
}//退出方法,s自动无效,s可以被回收,Stack内部的引用自然没了,所以
//这里也可以自愈,而且可以说这个方法不存在内存泄露问题,不过是晚一点
//交给GC而已,因为它是封闭的,对外不开放,可以说上面的代码99.9999%的
//情况是不会造成任何影响的,当然你写这样的代码不会有什么坏的影响,但是
//绝对可以说是垃圾代码!没有矛盾吧,我在里面加一个空的for循环也不会有
//什么太大的影响吧,你会这么做吗?
}
详解Java语言中内存泄漏及如何检测问题 (1)一般来说内存泄漏有两种情况 。一种情况,在堆中java内存泄漏的代码的分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉(如指针重新赋值);另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用) 。第一种情况,在Java中已经由于垃圾回收机制的引入 , 得到了很好的解决 。所以,Java中的内存泄漏,主要指的是第二种情况 。
可能光说概念太抽象了,大家可以看一下这样的例子java内存泄漏的代码:
1 Vector v=new Vector(10);
2 for (int i=1;i100; i){
【java内存泄漏的代码 java 内存泄漏】3 Object o=new Object();
4 v.add(o);
5 o=null;
6 }
在这个例子中,代码栈中存在Vector对象的引用v和Object对象的引用o 。在For循环中 , 我们不断的生成新的对象,然后将其添加到Vector对象中,之后将o引用置空 。问题是当o引用被置空后,如果发生GC , 我们创建的Object对象是否能够被GC回收呢?答案是否定的 。因为,GC在跟踪代码栈中的引用时,会发现v引用 , 而继续往下跟踪,就会发现v引用指向的内存空间中又存在指向Object对象的引用 。也就是说尽管o引用已经被置空,但是Object对象仍然存在其java内存泄漏的代码他的引用 , 是可以被访问到的,所以GC无法将其释放掉 。如果在此循环之后,Object对象对程序已经没有任何作用,那么我们就认为此Java程序发生了内存泄漏 。
尽管对于C/C中的内存泄露情况来说,Java内存泄露导致的破坏性小,除了少数情况会出现程序崩溃的情况外,大多数情况下程序仍然能正常运行 。但是,在移动设备对于内存和CPU都有较严格的限制的情况下 , Java的内存溢出会导致程序效率低下、占用大量不需要的内存等问题 。这将导致整个机器性能变差,严重的也会引起抛出OutOfMemoryError,导致程序崩溃 。
一般情况下内存泄漏的避免
在不涉及复杂数据结构的一般情况下,Java的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度 。我们有时也将其称为“对象游离” 。
例如java内存泄漏的代码:
1 public class FileSearch{
2
3 private byte[] content;
4 private File mFile;
5
6 public FileSearch(File file){
7 mFile = file;
8 }
9
10 public boolean hasString(String str){
11 int size = getFileSize(mFile);
12 content = new byte[size];
13 loadFile(mFile, content);
14
15 String s = new String(content);
16 return s.contains(str);
17 }
18 }
在这段代码中,FileSearch类中有一个函数hasString,用来判断文档中是否含有指定的字符串 。流程是先将mFile加载到内存中 , 然后进行判断 。但是,这里的问题是,将content声明为了实例变量,而不是本地变量 。于是 , 在此函数返回之后,内存中仍然存在整个文件的数据 。而很明显,这些数据我们后续是不再需要的,这就造成了内存的无故浪费 。
要避免这种情况下的内存泄露,要求我们以C/C的内存管理思维来管理自己分配的内存 。第一,是在声明对象引用之前,明确内存对象的有效作用域 。在一个函数内有效的内存对象 , 应该声明为local变量,与类实例生命周期相同的要声明为实例变量……以此类推 。第二,在内存对象不再需要时,记得手动将其引用置空 。
复杂数据结构中的内存泄露问题
在实际的项目中,我们经常用到一些较为复杂的数据结构用于缓存程序运行过程中需要的数据信息 。有时 , 由于数据结构过于复杂,或者我们存在一些特殊的需求(例如 , 在内存允许的情况下,尽可能多的缓存信息来提高程序的运行速度等情况),我们很难对数据结构中数据的生命周期作出明确的界定 。这个时候,我们可以使用Java中一种特殊的机制来达到防止内存泄露的目的 。
之前我们介绍过,Java的GC机制是建立在跟踪内存的引用机制上的 。而在此之前 , 我们所使用的引用都只是定义一个“Object o;”这样形式的 。事实上,这只是Java引用机制中的一种默认情况 , 除此之外,还有其他的一些引用方式 。通过使用这些特殊的引用机制 , 配合GC机制,就可以达到一些我们需要的效果 。
Java 程序里的内存泄漏Java 程序里的内存泄漏是如何表现的大多数程序员都知道使用类似于 Java 的编程语言的好处之一就是他们无需再为内存的分配和释放所担心了 你只需要简单地创建对象 当它们不再为程序所需要时 Java 会自行通过一个被称为垃圾收集的机制将其移除 这个过程意味着 Java 已经解决了困扰其他编程语言的一个棘手的问题 可怕的内存泄漏 果真是这样的吗?在进行深入讨论之前 让我们先回顾一下垃圾收集是如何进行实际工作的 垃圾收集器的工作就是找到程序不再需要的对象并在当它们不再被访问或引用时将它们移除掉 垃圾收集器从贯穿整个程序生命周期的类这个根节点开始 扫描所有引用到的节点 在遍历节点时 它跟踪那些被活跃引用着的对象 那些不再被引用的对象就满足了垃圾回收的条件 当这些对象被移除时被它们占用的内存资源会交还给 Java 虚拟机(JVM)因此 Java 代码的确不需要程序员负责内存管理的清理工作 它自行对不再使用的对象进行垃圾收集 然而 需要记住的是 垃圾收集的关键在于一个对象在不再被引用时才被统计为不再使用 下图对这一概念进行了说明
编写一段Java代码 , 展现java中会存在内存泄漏的问题 。内存泄漏示例
在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身,那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的 。因此,如果对象加入到Vector 后 , 还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null 。
Vector v = new Vector(10);
for (int i = 1; i100; i){
Object o = new Object();
v.add(o);
o = null;
}// 此时,所有的Object 对象都没有被释放 , 因为变量v 引用这些对象 。实际上无用,而还被引用的对象 , GC 就无能为力了(事实上GC 认为它还有用),这一点是导致内存泄漏最重要的原因 。
如何用Java编写一段代码引发内存泄露其实Java中不可能存在内存泄漏,因为GC会在必要的时候回收内存 。
这个例子没有体现内存泄漏,但是用来理解内存泄漏的潜在发生可能还是可以的 。
不需要那么复杂,一个非常简单的例子就能说明问题:
Object o1 = new Object();
Object o2 = o1;
o1 = null; // 这时o1指向的那个对象回收了吗?没有,因为它还被o2引用着
o2 = null; // 这样才能回收
实际应用中 , 只要o2的作用域很小,不执行o2=null也是没有问题的 , 因为只要o2过了它的生存期,它指向的对象就能被回收 。
结论是,作用域越大的变量 , 越要引起重视,因为它可能占用着某些对象引用而导致对象不能被回收 。换句话说 , 尽可能地缩小变量的作用域——这也是你在Java中关于内存方面能做的唯一努力了 。---引用别人的
java内存泄露是什么意思?Java内存泄露\x0d\x0a一般来说内存泄漏有两种情况 。一种情况如在C/C语言中的,在堆中的分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉(如指针重新赋值);另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用) 。第一种情况 , 在Java中已经由于垃圾回收机制的引入,得到了很好的解决 。所以 , Java中的内存泄漏,主要指的是第二种情况 。\x0d\x0a可能光说概念太抽象了 , 大家可以看一下这样的例子:\x0d\x0a1Vectorv=newVector(10);\x0d\x0a2for(inti=1;i
回答于 2022-12-14
java内存泄漏的代码的介绍就聊到这里吧,感谢你花时间阅读本站内容 , 更多关于java 内存泄漏、java内存泄漏的代码的信息别忘了在本站进行查找喔 。

    推荐阅读