java - 这些对象会被GC回收吗?

标签 java android garbage-collection observer-pattern

考虑以下java代码

public class PlayerView implements IPlayerListener
{
    public Player player;

    public PlayerView()
    {
        player = new Player();
        player.listener = this;
    }

    public void onPlayerEvent()
    {

    }
}

public class Player
{
    public IPlayerListener listener;

    public void foo()
    {
        //do something then
        if(this.listener != null)
        {
            this.listener.onPlayerEvent();
        }

    }
}

public interface IPlayerListener
{
    public void onPlayerEvent();
}

这里我有一个 PlayerView 和 Player。 Player 需要向 PlayerView 报告事件,因此我制作了一个名为 IPlayerListener 的接口(interface),Player 可能具有 PlayerListener 对象的引用以向其报告事件。

(我知道在 Java 中这不是创建事件的最佳方式,但我真的不需要“很多监听器”来使用默认的“addEventListener”模式)

问题#1:当PlayerView对象设置为null时,PlayerView和Player对象是否都会被GC回收?

如果是,则继续执行下面的代码

public class PlayerView implements IPlayerListener, IPlaylistListener
{
    public Player player;

    public PlayerView()
    {
        player = new Player();
        player.listener = this;
        player.playlist = new Playlist();
        player.playlist.listener = this;
    }

    public void onPlayerEvent()
    {

    }

    public void onPlaylistEvent()
    {

    }
}

public class Player
{
    public Playlist playlist;
    public IPlayerListener listener;

    public void foo()
    {
        //do something then
        if(this.listener != null)
        {
            this.listener.onPlayerEvent();
        }

    }
}

public class Playlist
{
    public IPlaylistListener listener;

    public void bar()
    {
        //do something then
        if(this.listener != null)
        {
            this.listener.onPlaylistEvent();
        }
    }
}

public interface IPlayerListener
{
    public void onPlayerEvent();
}

public interface IPlaylistListener
{
    public void onPlaylistEvent();
}

这里我添加了第三个类,Playlist 类,Player 也有一个播放列表对象的引用。 播放列表也应该有一个听众/观察者。在这种情况下,PlayerView 也是播放列表监听器。

问题#2:当PlayerView对象设置为null时,这些对象会被GC回收吗?

如果答案 #2 是否定的,那么请继续

public class PlayerView implements IPlayerListener, IPlaylistListener
{
    public Player player;

    public PlayerView()
    {
        player = new Player();
        player.listener = this;
        player.playlist = new Playlist();
        player.playlist.parentPlayer = player;
    }

    public void onPlayerEvent()
    {

    }

    public void onPlaylistEvent()
    {

    }
}

public class Player
{
    public Playlist playlist;
    public IPlayerListener listener;

    public void foo()
    {
        //do something then
        if(this.listener != null)
        {
            this.listener.onPlayerEvent();
        }

    }
}

public class Playlist
{
    public Player parentPlayer;

    public void bar()
    {
        //do something then
        if(this.parentPlayer != null)
        {
            if(this.parentPlayer.listener != null)
            {
                if(this.parentPlayer.listener instanceof IPlaylistListener)
                {
                    ((IPlaylistListener) this.parentPlayer.listener).onPlaylistEvent();
                }
            }
        }
    }
}

public interface IPlayerListener
{
    public void onPlayerEvent();
}

public interface IPlaylistListener
{
    public void onPlaylistEvent();
}

在这里,我将 playlistListener 引用切换为对父 Player 的引用,而不是直接调用 playlistListener,而是检查 playlistListener 是否也是一个 PlaylistListener(或者两个接口(interface)可以合并为一个)

问题 #3:前面的代码是否可以解决问题并收集所有对象?

或者我应该更好地使用第二个代码块并在 PlayerView 对象中找到正确的时间(就像在 PlayerView 对象从其父 View 中删除之前一样)并且至少调用“player.playlist.listener = null;”。

最佳答案

重要的是要认识到,理论上不可能预测一个对象何时会被垃圾回收。更具体地说,将字段设置为 null 不会导致它被收集。相反,它可能会导致它变得不可访问,因此有资格被垃圾收集。这意味着它可能在随后的某些 GC 运行中被收集,但不一定是下一次运行。 (请注意,即使调用 System.gc() 也不能保证会收集符合条件的对象。JVM 可以随意忽略 gc() 调用。)

注意:可达性是指某个 Activity 线程是否仍可以访问该对象。如果一个线程可以跟随引用链到达某个对象,那么它就是可达的。自然地,链需要从线程可以访问的引用变量开始;例如线程堆栈上的静态变量或局部变量或参数。


所以对于你的具体问题:

Question #1: When PlayerView object is set to null, will both the PlayerView and Player object be collected by GC?

该代码既没有创建 PlayerView 实例,也没有可以为 null 的 PlayerView 变量。我还注意到 Player 和 PlayerView 对象指向彼此。这个引用周期不直接影响可达性。虽然它确实意味着如果其中一个对象是可达的,那么两者都是可达的。

因此,如果我们假设只有一个 PlayerView 变量......并且没有 Player 变量......然后将 null 分配给变量将导致两个对象都变得不可访问,因此有资格被收集。

Question #2: When PlayerView object is set to null, will these objects be collected by GC?

同样,需要注意的是,当对 PlayerView 的最后一个可访问引用为空(或当它变得不可访问时),所有三个对象都将有资格被收集。


一些建议:

  1. 您可能过于担心何时以及如何回收对象。它很可能不会产生丝毫影响。
  2. 显式清零事物以使其被收集通常是浪费时间。
  3. 无需担心 Java 中的引用循环。 Java GC 不基于引用计数,无需中断循环即可使 GC 工作。

关于java - 这些对象会被GC回收吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12882400/

相关文章:

java - 如何使用 Unicode 将日语和英语分开

java - 当对实体使用注释和 hbm 混合时,Spring/Hibernate 无法初始化 EntityManager

java - 如何从http请求中获取json响应?

java - 正则表达式分组和可选匹配

java - 如何使用jsp生成唯一字符串?

android - 如何在 Chromecast App 中重新连接 Activity 时处理 GoogleApiClient 实例?

Android:使用 edittext 输入设置按钮的文本?

android - 是安卓:excludeFromRecents broken for the first app that is launched on the device on Android L?

android - GC_CONCURRENT 日志消息中的 "paused"值是什么?

objective-c - 既然 Objective-C/Cocoa 有垃圾收集功能,我还需要学习管理内存吗?