内存泄漏示例 - 引用和对象
Memory Leak Example -references and objects
我有以下 method.Suppose 我从 class B
调用了 A.m1()
10,000 次。
因此,所有 10,000 个 MyObj
对象都将被垃圾回收,因为它们的范围仅在 m1()
方法内。
没有内存泄漏?
class A {
String m1() {
MyObj obj = new Mybj();
}
}
我在下面称呼它
class B {
void m2() {
String s = classAObj.m1();
}
}
我认为您具有 C++ 背景。在 Java 中,由于其垃圾收集系统,很难出现内存泄漏。垃圾收集可能会变得复杂,但基本思想是有一个程序不断 运行 在后台寻找堆中未使用的对象,当它找到一个时,它会删除它。因此,当您退出 m1()
方法时,没有对新 Mybj()
对象的引用,因此垃圾收集器将其删除。
方法中创建的引用在超出范围时最终会被垃圾回收。但这不一定立即发生。
这里有一个展示引用收集的demo。但首先
一些术语。
- 硬引用 - 对 object 的正常引用将在
附近,直到它被垃圾收集。这些是 object 创建的
的典型实例值。
- 弱引用 - 指向与硬引用相同 object 的引用。
当垃圾收集硬引用时,也会收集关联的弱引用。
这是如何工作的。
- 方法
m1
被调用 n
次,每次都创建 A
实例的弱引用并 return 调用它。
- 然后将其添加到列表中。
- 一旦硬引用被垃圾回收,引用相同object的弱引用也将被回收
- 当尝试检索其关联的
object. 时,弱引用将 return 为 null
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class GarbageCollection {
public static void main(String[] args) {
// get out of static context
new GarbageCollection().start();
}
public void start() {
int n = 10_000;
List<WeakReference<A>> weak = new ArrayList<>();
通过调用 m1
和 return 引用来创建 A
的 n
弱引用。
然后它添加到 List
.
for (int i = 0; i < n; i++) {
WeakReference<A> wk = m1();
weak.add(wk);
}
现在遍历弱引用列表,看看有多少是空的。
预计为零
,因为垃圾收集器尚未运行。在 m1
中创建的所有那些 A
分配仍然潜伏在堆中。
int count = 0;
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
System.out.println(count); // probably zero
现在重复相同的过程,但明确调用垃圾收集器。
count = 0;
System.gc();
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
此时,count 应该是 non-zero(或者 n
小值 n
)到
显示部分或全部 object 已收集。
System.out.println(count);
}
public WeakReference<A> m1() {
A a = new A();
return new WeakReference<>(a);
}
}
class A {
}
我有以下 method.Suppose 我从 class B
调用了 A.m1()
10,000 次。
因此,所有 10,000 个 MyObj
对象都将被垃圾回收,因为它们的范围仅在 m1()
方法内。
没有内存泄漏?
class A {
String m1() {
MyObj obj = new Mybj();
}
}
我在下面称呼它
class B {
void m2() {
String s = classAObj.m1();
}
}
我认为您具有 C++ 背景。在 Java 中,由于其垃圾收集系统,很难出现内存泄漏。垃圾收集可能会变得复杂,但基本思想是有一个程序不断 运行 在后台寻找堆中未使用的对象,当它找到一个时,它会删除它。因此,当您退出 m1()
方法时,没有对新 Mybj()
对象的引用,因此垃圾收集器将其删除。
方法中创建的引用在超出范围时最终会被垃圾回收。但这不一定立即发生。
这里有一个展示引用收集的demo。但首先 一些术语。
- 硬引用 - 对 object 的正常引用将在
附近,直到它被垃圾收集。这些是 object 创建的
的典型实例值。 - 弱引用 - 指向与硬引用相同 object 的引用。
当垃圾收集硬引用时,也会收集关联的弱引用。
这是如何工作的。
- 方法
m1
被调用n
次,每次都创建A
实例的弱引用并 return 调用它。 - 然后将其添加到列表中。
- 一旦硬引用被垃圾回收,引用相同object的弱引用也将被回收
- 当尝试检索其关联的
object. 时,弱引用将 return 为 null
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class GarbageCollection {
public static void main(String[] args) {
// get out of static context
new GarbageCollection().start();
}
public void start() {
int n = 10_000;
List<WeakReference<A>> weak = new ArrayList<>();
通过调用 m1
和 return 引用来创建 A
的 n
弱引用。
然后它添加到 List
.
for (int i = 0; i < n; i++) {
WeakReference<A> wk = m1();
weak.add(wk);
}
现在遍历弱引用列表,看看有多少是空的。
预计为零
,因为垃圾收集器尚未运行。在 m1
中创建的所有那些 A
分配仍然潜伏在堆中。
int count = 0;
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
System.out.println(count); // probably zero
现在重复相同的过程,但明确调用垃圾收集器。
count = 0;
System.gc();
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
此时,count 应该是 non-zero(或者 n
小值 n
)到
显示部分或全部 object 已收集。
System.out.println(count);
}
public WeakReference<A> m1() {
A a = new A();
return new WeakReference<>(a);
}
}
class A {
}