如果 activity 具有在别处引用的静态成员变量,它可以被垃圾回收吗?
Can an activity be garbage collected if it has static member variables who are referenced elsewhere?
假设一个 Activity A 有一些静态成员变量,因为静态变量是在 class 第一次被 VM 加载并停留在内存中时加载的,我想知道 Activity 会发生什么关于垃圾收集,如果其他 class B 持有 class A 的任何静态变量。?
不会收吗?
会不会被收集并初始化为初始值?
您不能引用 静态变量(或任何变量)Class。
只能保存对对象的引用,不能保存变量本身。
例如,
class MainActivity {
public static Object obj = new Object();
}
class B {
private Object ref = MainActivity.obj;
}
在这种情况下,只有 new Object()
被 B
引用(因此无法进行 GC)。不是变量 obj
(或 class MainActivity
)本身。
Class用于示例目的
public class Activity {
public static int primitiveStatic = 42;
public static Object objectStatic = new Object();
}
public class B {
public Object referenceField = null;
}
public class C {
public int primitiveField = 0;
}
Java 对象实例的简单模型是一个内存区域,除了每个实例成员 (non-static) 的 space 外,还包含一些管理信息,包括对其 class 对象的引用。 class对象(运行时内存中的实体)包含关于class的各种信息,包括(与此问题相关的)space对于 class 的每个静态成员。请注意,其中一些依赖于 JVM。
需要注意的关键是静态成员在运行时存储在class对象中或与一起存储(不是在任何实例对象中)。
在上面的例子classes中,Activity
class对象在运行时会有两个变量,一个原始整数变量(primitiveStatic
)和一个引用Object
类型 (objectStatic
)。 class 的每个实例都有自己独特的内存区域,其中仅包含对 class 对象的单个引用。 B
的实例具有 space 用于单个对象引用。 C
的实例具有 space 单个原始整数值。
垃圾收集器可以移除并终结内存中任何符合收集条件的对象。这 也适用于 class 对象,但它不像实例对象那么简单,如果没有对它的引用,则该对象是合格的。 Class 对象和静态字段很少符合条件,但在卸载 class 的情况下,它们是符合条件的。有关 class 卸载的更多信息,请参阅 this documentation。
我相信你想知道的案例包括这些:
案例一
new Activity();
//or
Activity a = new Activity();
a = null;
设置和分配完成后的案例 1。
加载 class,创建 class 对象和静态变量,如上所述。如上所述,创建了一个实例。该实例立即符合垃圾回收条件。收集时,实例被销毁,删除对 class 对象的引用。如果它是程序结束或在其他某些情况下,class 对象也可能被垃圾收集,删除 primitiveStatic
和 objectStatic
变量。在这种情况下,objectStatic
所引用的 new Object()
现在也没有对它的引用,因此可以按正常方式进行垃圾回收。
案例二
B b = new B();
b.referenceField = Activity.objectStatic;
设置和分配完成后的情况 2。
创建了一个新的 B
实例(以及 class B
的 class 对象),如上所述。加载 Activity
class 并创建 class 对象(如果尚未创建)。 b
中的 referenceField
设置为引用与 objectStatic
字段相同的位置,该字段在 Activity
[=156= 中或与 Activity
class 对象。如果 Activity
class 被卸载(在某些情况下发生但不常见),它的 class 对象将被删除,如 //1
中所述。这一次,new Object()
仍然有对它的引用,在 b.referenceField
中,因此不符合收集条件。我们剩下 B
class 对象和 new Object()
以及一个实例 b
,每个实例都有一个引用。
案例三
Activity a = new Activity();
B b = new B();
b.referenceField = a.objectStatic;
a = null;
设置和分配完成后的案例 3。
加载 Activity
class,并创建 class 对象(如果尚未创建),如上所述。如上所述,创建了一个实例。 B
class 也一样。通过找到 a
的 class 引用并将其定位在那里,静态引用 objectStatic
从 a
获得并分配给 b.referenceField
。这是对引用值的复制赋值,所以b
和a
或Activity
之间没有引用,但是b
现在包含对 Activity
class 构造的 new Object()
的引用。 a = null
表示 a
最初引用的 Activity
实例符合垃圾回收条件。它对 Activity
class 对象的引用被删除。 Activity
class 对象可能符合垃圾回收条件。如果是,则清除它包含的静态字段。 objectStatic
引用的 new Object()
现在在 b
中只有一个引用,因此不符合垃圾回收条件。我们留下了这个对象,B
class 对象,以及 b
其中包含对每个对象的单个引用(与案例 //2
相同)
案例4
Activity a = new Activity();
C c = new C();
c.primitiveField = a.primitiveStatic;
a = null;
设置和分配完成后的案例 4。
与 //3
一样,加载 Activity
class,并创建 class 对象(如果尚未创建),并创建一个实例,如所述多于。 C
class 也一样。通过找到 a
的 class 引用并将其定位在那里,静态原语 primitiveStatic
从 a
获得并分配给 c.primitiveField
。这只是一个复制赋值,所以c
和a
或Activity
之间没有引用。 a = null
表示Activity
最初由 a
引用的实例符合垃圾回收条件。它对 Activity
class 对象的引用被删除。 Activity
class 对象可能符合垃圾回收条件。如果是,则清除它包含的静态字段。 objectStatic
引用的 new Object()
现在没有引用,因此可以进行垃圾回收。我们剩下 C
实例 c
,其 primitiveField
.
中的原始 int 值为 42
在所有这些情况下,没有任何对象实例被其他引用对象的对象所阻止,这些对象也被其 class 静态字段引用(甚至 class 及其在某些情况下,静态值可以被垃圾收集),即使这些字段值是 class 的 'owned'(例如 final
并在 class 中初始化并由 class 初始化)
需要注意的是,如果objectStatic
字段是final
,它所指向的对象几乎永远不会被收集:Activity
class必须卸下它才有资格收集。如果您有很多在程序设置后未使用的静态对象引用,这可能会成为一个问题,因为即使它们未被使用,它们也会留下并填满内存。
假设一个 Activity A 有一些静态成员变量,因为静态变量是在 class 第一次被 VM 加载并停留在内存中时加载的,我想知道 Activity 会发生什么关于垃圾收集,如果其他 class B 持有 class A 的任何静态变量。? 不会收吗? 会不会被收集并初始化为初始值?
您不能引用 静态变量(或任何变量)Class。
只能保存对对象的引用,不能保存变量本身。
例如,
class MainActivity {
public static Object obj = new Object();
}
class B {
private Object ref = MainActivity.obj;
}
在这种情况下,只有 new Object()
被 B
引用(因此无法进行 GC)。不是变量 obj
(或 class MainActivity
)本身。
Class用于示例目的
public class Activity {
public static int primitiveStatic = 42;
public static Object objectStatic = new Object();
}
public class B {
public Object referenceField = null;
}
public class C {
public int primitiveField = 0;
}
Java 对象实例的简单模型是一个内存区域,除了每个实例成员 (non-static) 的 space 外,还包含一些管理信息,包括对其 class 对象的引用。 class对象(运行时内存中的实体)包含关于class的各种信息,包括(与此问题相关的)space对于 class 的每个静态成员。请注意,其中一些依赖于 JVM。
需要注意的关键是静态成员在运行时存储在class对象中或与一起存储(不是在任何实例对象中)。
在上面的例子classes中,Activity
class对象在运行时会有两个变量,一个原始整数变量(primitiveStatic
)和一个引用Object
类型 (objectStatic
)。 class 的每个实例都有自己独特的内存区域,其中仅包含对 class 对象的单个引用。 B
的实例具有 space 用于单个对象引用。 C
的实例具有 space 单个原始整数值。
垃圾收集器可以移除并终结内存中任何符合收集条件的对象。这 也适用于 class 对象,但它不像实例对象那么简单,如果没有对它的引用,则该对象是合格的。 Class 对象和静态字段很少符合条件,但在卸载 class 的情况下,它们是符合条件的。有关 class 卸载的更多信息,请参阅 this documentation。
我相信你想知道的案例包括这些:
案例一
new Activity();
//or
Activity a = new Activity();
a = null;
设置和分配完成后的案例 1。
加载 class,创建 class 对象和静态变量,如上所述。如上所述,创建了一个实例。该实例立即符合垃圾回收条件。收集时,实例被销毁,删除对 class 对象的引用。如果它是程序结束或在其他某些情况下,class 对象也可能被垃圾收集,删除 primitiveStatic
和 objectStatic
变量。在这种情况下,objectStatic
所引用的 new Object()
现在也没有对它的引用,因此可以按正常方式进行垃圾回收。
案例二
B b = new B();
b.referenceField = Activity.objectStatic;
设置和分配完成后的情况 2。
创建了一个新的 B
实例(以及 class B
的 class 对象),如上所述。加载 Activity
class 并创建 class 对象(如果尚未创建)。 b
中的 referenceField
设置为引用与 objectStatic
字段相同的位置,该字段在 Activity
[=156= 中或与 Activity
class 对象。如果 Activity
class 被卸载(在某些情况下发生但不常见),它的 class 对象将被删除,如 //1
中所述。这一次,new Object()
仍然有对它的引用,在 b.referenceField
中,因此不符合收集条件。我们剩下 B
class 对象和 new Object()
以及一个实例 b
,每个实例都有一个引用。
案例三
Activity a = new Activity();
B b = new B();
b.referenceField = a.objectStatic;
a = null;
设置和分配完成后的案例 3。
加载 Activity
class,并创建 class 对象(如果尚未创建),如上所述。如上所述,创建了一个实例。 B
class 也一样。通过找到 a
的 class 引用并将其定位在那里,静态引用 objectStatic
从 a
获得并分配给 b.referenceField
。这是对引用值的复制赋值,所以b
和a
或Activity
之间没有引用,但是b
现在包含对 Activity
class 构造的 new Object()
的引用。 a = null
表示 a
最初引用的 Activity
实例符合垃圾回收条件。它对 Activity
class 对象的引用被删除。 Activity
class 对象可能符合垃圾回收条件。如果是,则清除它包含的静态字段。 objectStatic
引用的 new Object()
现在在 b
中只有一个引用,因此不符合垃圾回收条件。我们留下了这个对象,B
class 对象,以及 b
其中包含对每个对象的单个引用(与案例 //2
相同)
案例4
Activity a = new Activity();
C c = new C();
c.primitiveField = a.primitiveStatic;
a = null;
设置和分配完成后的案例 4。
与 //3
一样,加载 Activity
class,并创建 class 对象(如果尚未创建),并创建一个实例,如所述多于。 C
class 也一样。通过找到 a
的 class 引用并将其定位在那里,静态原语 primitiveStatic
从 a
获得并分配给 c.primitiveField
。这只是一个复制赋值,所以c
和a
或Activity
之间没有引用。 a = null
表示Activity
最初由 a
引用的实例符合垃圾回收条件。它对 Activity
class 对象的引用被删除。 Activity
class 对象可能符合垃圾回收条件。如果是,则清除它包含的静态字段。 objectStatic
引用的 new Object()
现在没有引用,因此可以进行垃圾回收。我们剩下 C
实例 c
,其 primitiveField
.
在所有这些情况下,没有任何对象实例被其他引用对象的对象所阻止,这些对象也被其 class 静态字段引用(甚至 class 及其在某些情况下,静态值可以被垃圾收集),即使这些字段值是 class 的 'owned'(例如 final
并在 class 中初始化并由 class 初始化)
需要注意的是,如果objectStatic
字段是final
,它所指向的对象几乎永远不会被收集:Activity
class必须卸下它才有资格收集。如果您有很多在程序设置后未使用的静态对象引用,这可能会成为一个问题,因为即使它们未被使用,它们也会留下并填满内存。