2016-05-04 23 views
2

我有一个应用程序,我故意引入一个空指针异常。我将用一个代码示例来解释如下:如何在死亡后检查过程状态,或者甚至可能?

// access modifiers omitted for brevity 
class MyApplication extends Application { 

    String name; 

    String getName() { 
     return name; 
    } 

    void setName(String name) { 
     this.name = name; 
    } 
} 

// ============================== ======

// access modifiers omitted for brevity 
class WhatIsYourNameActivity extends Activity { 

    void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.writing); 

     // Just assume that in the real app we would really ask it! 
     MyApplication app = (MyApplication) getApplication(); 
     app.setName("Developer Phil"); 
     startActivity(new Intent(this, GreetLoudlyActivity.class)); 

    } 

} 

// =================================== ===================

// access modifiers omitted for brevity 
class GreetLoudlyActivity extends Activity { 

    TextView textview; 

    void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.reading); 
     textview = (TextView) findViewById(R.id.message); 
    } 

    void onResume() { 
     super.onResume(); 

     MyApplication app = (MyApplication) getApplication(); 
     textview.setText("HELLO " + app.getName().toUpperCase()); 
    } 
} 

用户启动应用程序。 在WhatIsYourNameActivity中,您询问用户的姓名并将其存储在MyApplication中。 在GreetLoudlyActivity中,您从MyApplication对象中获取用户名并显示它。 用户使用主页按钮离开应用程序。 几个小时后,Android默默地杀死了应用程序以回收一些内存。

到目前为止,太棒了!

但是这里出现了令人失望的部分...

用户重新打开该应用程序。 Android创建一个新的MyApplication实例并恢复GreetLoudlyActivity。 GreetLoudlyActivity会提取用户名称,该名称现在为空,并且会发生NullPointerException异常。

发生崩溃是因为Application对象是全新的,所以name变量为null,当我们调用String#toUpperCase()时,会导致NullPointerException。

命令行,当你在一个仿真器或扎根电话运行此: 启动应用程序,然后:

adb shell ps 

按家设备和命令行:

adb shell ps | grep com.crashy.package 

和:

adb shell kill <PID from above step> 

现在,我们尝试从后台使用最近应用程序带回应用程序t abs,它会像预期的那样崩溃。问题是如何列出与进程一起杀死的所有对象的状态 - 或者是否杀死一个进程来杀死所有关联的对象?有没有办法分叉这个过程?

+0

您可以在'WhatIsYourNameActivity'中存储用户名,并将其作为'Intent Bundle'传递给'GreetLoudlyActivity'并将其存储在那里。 – Grender

+0

这不是我的问题。我故意介绍这个问题,我想分析当一个进程死亡时究竟发生了什么。对强引用的对象会发生什么? – Skynet

+0

虽然这不是一个答案,但为什么你将名称存储在Application类中,为什么不在共享的pref中呢? – varunkr

回答

2

“...或者杀死进程杀死所有关联的对象?”

这正是发生的情况。当一个进程被终止时,它所拥有的所有内存都被操作系统回收 - 如果没有发生这种情况,每当进程终止并且操作系统最终会耗尽内存时,都会发生内存泄漏。

一旦进程/应用程序终止,您将失去未保存到永久存储的所有内容。

-1

问题是你想用一个简单的变量来模拟持久存储。为了更好地理解,我将研究Android活动的生命周期,以了解应用程序如何以及何时“被杀”http://developer.android.com/training/basics/activity-lifecycle/index.html

现在要建议使用共享首选项管理器。(您的数据看起来并不大到足以证明一个sqlLite DB)

在您的存储活动保存名称与此

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this) 
Preferences.Editor edit = preferences.edit(); 
edit.putString('name', 'someName'); 
edit.commit(); 

并与检索它在你的其他活动

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this) 
preferences.getString('name'); 
+0

这不是我的问题。当一个进程被杀害时会发生什么?一个过程是分叉的?当一个流程分叉时会发生什么?在分叉过程之后,子进程的地址空间被新的进程数据覆盖。这是通过对系统的exec调用完成的。 – Skynet

+0

fork-and-exec机制因此将新命令与旧命令切换,而新程序的执行环境保持不变,包括输入和输出设备的配置,环境变量和优先级。该机制用于创建所有UNIX进程,因此它也适用于Linux操作系统。即使是第一个具有进程ID 1的进程init,在引导过程中也会在所谓的引导程序中分叉。 – Skynet

+0

那么对象在哪里? – Skynet