英文:
Memory Leak Example -references and objects
问题
我有下面的方法。假设我从类B中调用A.m1()
共10000次。因此,所有10000个MyObj
对象将被垃圾回收,因为它们的范围仅限于m1()
方法内部。没有内存泄漏?
class A {
String m1() {
MyObj obj = new MyObj();
}
}
我在下面进行调用:
class B {
void m2() {
String s = classAObj.m1();
}
}
英文:
I have the below method.Suppose i call A.m1()
10,000 times from class B
.
So all 10,000 MyObj
objects will be garbage collected as their scope is only within the m1()
method.
There is no memory leak?
class A {
String m1() {
MyObj obj = new Mybj();
}
}
And i call it below
class B {
void m2() {
String s = classAObj.m1();
}
}
答案1
得分: 0
我认为你具有C++背景。在Java中,由于其垃圾回收系统,很难发生内存泄漏。垃圾回收可能会变得复杂,但基本思想是有一个在后台不断运行的程序,它在堆中查找未使用的对象,当找到一个时,就会删除它。所以当你退出m1()
方法时,不再有对新创建的Mybj()
对象的引用,因此垃圾回收器会将其删除。
英文:
I think you have a C++ background. In Java, it's quite hard to get a memory leak because of its garbage collection system. Garbage collection can get complicated, but the basic idea is there is a program constantly running in the background looking in the heap for an unused object, and when it finds one, it deletes it. So when you exit the m1()
method, there are no references to the new Mybj()
object so the garbage collector deletes it.
答案2
得分: 0
方法中创建的引用在其作用域结束时最终会被垃圾回收。但不一定会立即发生。
下面是一个演示,展示了引用是如何被收集的。但首先,解释一些术语。
- 强引用(hard reference)- 对象的正常引用,直到被垃圾回收之前都将存在。这些是从对象创建中产生的典型实例值。
- 弱引用(weak references)- 指向与强引用相同对象的引用。当强引用被垃圾回收时,关联的弱引用也将被回收。
工作原理:
- 方法 `m1` 被调用了 `n` 次,每次都会创建一个 `A` 类实例的弱引用并返回它。
- 然后将其添加到列表中。
- 一旦强引用被垃圾回收,指向相同对象的弱引用也将被收集。
- 此时尝试检索其关联对象时,弱引用将返回 null。
```java
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) {
// 脱离静态上下文
new GarbageCollection().start();
}
public void start() {
int n = 10_000;
List<WeakReference<A>> weak = new ArrayList<>();
通过调用 m1
创建 n
个 A
类的弱引用,并将引用添加到列表中。
for (int i = 0; i < n; i++) {
WeakReference<A> wk = m1();
weak.add(wk);
}
现在遍历弱引用列表,查看有多少个为 null。
预期为零,因为垃圾回收器尚未运行。在 m1
中创建的所有 A
实例仍然存在于堆中。
int count = 0;
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
System.out.println(count); // 可能为零
现在重复相同的过程,但显式调用垃圾回收器。
count = 0;
System.gc();
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
此时,计数应为非零(或者对于小值的 n
可能为 n
),以显示已收集部分或全部对象。
System.out.println(count);
}
public WeakReference<A> m1() {
A a = new A();
return new WeakReference<>(a);
}
}
class A {
}
<details>
<summary>英文:</summary>
The references created in the method are eventually garbage collected when they go out of scope. But it doesn't necessary happen immediately.
Here is a demo that shows that the references are collected. But first
some terms.
- hard reference - A normal reference to an object that will be around <br>until it is garbage collected. These are the typical instance values resulting<br> from object creation.
- weak references - references that point to the same object as a hard reference.<br> When a hard reference is garbage collected, the associated weak references are also collected.
How this works.
- The method `m1` is called `n` times, each time creating a weak reference of an instance of `A` and returning it.
- This is then added to a list.
- Once the hard references are garbage collected, the weak references that refer to the same objects will also be collected
- The weak reference will then return null when trying to retrieve its associated<br> object.
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<>();
Create `n` weak references of `A` by calling `m1` and returning the reference.</div>
Then it add to the `List`.
for (int i = 0; i < n; i++) {
WeakReference<A> wk = m1();
weak.add(wk);
}
Now iterate thru the List of weak references to see how many are null.
Zero is expected<br> since the garbage collector has not yet run. All of those `A` allocations created in `m1` are still lurking around in the heap.
int count = 0;
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
System.out.println(count); // probably zero
Now repeat the same process but explicitly invoke the garbage collector.
count = 0;
System.gc();
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
At this point, count should be non-zero (or possibly `n` for small values of `n`) to<br> show some or all of the objects have been collected.
System.out.println(count);
}
public WeakReference<A> m1() {
A a = new A();
return new WeakReference<>(a);
}
}
class A {
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论