我的Java单例实例何时/为什么被销毁?

我的Java单例实例何时/为什么被销毁?,java,android,singleton,android-ndk,Java,Android,Singleton,Android Ndk,我有一个android应用程序,它被设置为启动Java活动(称为MyJavaActivity),然后启动一个NativeActivity。当NativeActivity完成时,它将返回MyJavaActivity 我还有一个Java singleton类(称之为MyJavaSingleton),我希望在应用程序的整个生命周期中都将其保留在内存中。我从我的NativeActivity(使用JNI)设置了一些singleton类的成员变量,这些变量稍后可以由MyJavaActivity检索 问题是,

我有一个android应用程序,它被设置为启动Java活动(称为MyJavaActivity),然后启动一个NativeActivity。当NativeActivity完成时,它将返回MyJavaActivity

我还有一个Java singleton类(称之为MyJavaSingleton),我希望在应用程序的整个生命周期中都将其保留在内存中。我从我的NativeActivity(使用JNI)设置了一些singleton类的成员变量,这些变量稍后可以由MyJavaActivity检索

问题是,在NativeActive退出之前,MyJavaSingleton实例似乎一直在内存中,但当MyJavaActivity再次启动时,它似乎又被设置为null,因此我在NativeActivity中设置的所有变量现在都重置为默认值。为什么会发生这种情况

 public class MyJavaActivity extends Activity implements View.OnTouchListener
 {
   @Override
   public void onCreate(Bundle savedInstanceState) 
   {
    super.onCreate(savedInstanceState);
    MyJavaSingleton.Instance().DoStuff();
   }

   @Override
   public boolean onTouch(View arg0, MotionEvent arg1) 
   {
      Intent intent = new Intent(MyJavaActivity.this, NativeActivity.class);
      startActivity(intent); // at this point, android_main will be executed 
   }
 }

 /////////////////////////////
 public class MyJavaSingleton
 {
   static private MyJavaSingleton mInstance = null;
    synchronized public static MyJavaSingleton Instance()
{
    if( mInstance == null )
    {
        mInstance = new MyJavaSingleton();
        Log.v(TAG, "New MyJavaSIngleton instance");
    }
    return mInstance;
}
 }
 /////////////////////////////
 // Native 
 void android_main(struct android_app* state) 
 {
     // Do various stuff, set some variables on the MyJavaSingleton
     // At this point, MyJavaSingleton.mInstance is still at the same address in memory, which is good //
     ANativeActivity_finish(state->activity);
     exit(0);
     // Problem: sometime after this exit and before MyJavaActivity::onCreate is called, MyJavaSingleton.mInstance is set to null! 
 }
在上面的代码提取中,“New MyJavaSIngleton instance”在应用程序首次启动时打印,然后在NativeActivity退出后(即android_main退出后)再次打印,并再次调用MyJavaActivity的onCreate


为什么重新进入MyJavaActivity时MyJavaSingleton.minInstance变为NULL

我会保密的。以防其他代码意外设置它。

每个Android应用程序都在自己的进程中运行,因此只要它继续运行,您的singleton就可以使用。当进程终止时,您的单例将丢失。因此,当重新启动应用程序时,需要重新创建此单例对象。

请务必阅读有关流程生命周期的文档:

在这种情况下,只要你的应用程序在后台(就活动而言,用户看不到你的任何活动),你的进程就可以随时终止。如果用户稍后返回到您的某个活动,将创建一个新进程并创建该活动的新实例。

“Android操作系统可以并且将终止您的单例,甚至不会告诉您。”

资料来源:

这篇文章的作者提出了一些解决方案,比如使用服务,或者对应用程序类进行子类化。后者似乎得到了相当多的支持:


为什么要调用exit()?这不是杀死了JVM,还是我对Android一无所知?是的,我也不喜欢调用exit(),我觉得这是一种黑客行为,但除非我这样做,否则应用程序似乎不会返回MyJavaActivity。@lost_bits1110
finish()
不起作用?正如@James所说的,singleton应该是私有的。另外,如前所述,
Instance()
应该是
同步的
@DeeV No,在我上面的代码片段中,您可以看到我将本机等价物调用为'finish()
,即
ANativeActivity\u finish
。只有这样(并且没有退出()
),应用程序不会返回到
MyJavaActivity
,它只会在显示的最后一个屏幕上停止@Hemal我在之前的评论中提到了这一点,但我最初将其设置为
private
,并且行为是相同的。我尝试添加“synchronized”,但结果仍然相同:(我将更新上面的代码以显示这两个更改。我不确定是谁投了否决票,但我最初将其设置为private,最后将其设置为public,以便我可以快速打印其地址值。设置为private仍会导致我的实例在退出NativeActivity后的某个时间点设置为NULL。我希望这是因为downvoter误击向下箭头而不是up@lost_bits1110如果它是私有的,我看不出它怎么能恢复为null,除非在同一个类中的其他地方被设置为
null
。反射可以用来将它恢复为null。但是在这种情况下,即使它是
公共的
,它也会被设置为null。嗯,我认为我没有使用reflec我也尝试过设置观察点-但是Eclipse在值更改时从不中断。我还在
MyJavaSingleton
中放置了一个
finalize
方法,带有一些打印语句和一个断点,这也不会被击中!SYes但我从未完全退出应用程序,应用程序只是从MyJavaActivity转到NativeActivi然后返回MyJavaActivity。我认为调用
退出
一定会终止进程,然后它以某种方式重新启动,使我回到
MyJavaActivity
。不幸的是,使用
退出
似乎是恢复到调用它的Java活动的唯一方法:(这是一个很好的评论,但是这个页面说“默认情况下,同一应用程序的所有组件都在同一个进程中运行”。我没有改变这个默认机制,所以我假设
NativeActivity
MyJavaActivity
MyJavaSingleton
都是同一进程的一部分。或者
MyJavaActivity
NativeActivity
在某些点上始终可见(在它们之间转换时除外),所以我不知道为什么我的应用程序的进程会被终止,或者为什么我原来的单例实例会丢失并创建一个新的单例实例。如果单例实例变为null,那么要么你在某个地方将其设置为null,要么你的进程会消失。如果你实际上从未离开前台,那么只有另一种方法可以让它消失y是指如果它崩溃或使用了太多内存,它必须被杀死。