Android 内存管理系统的问题
Issues on Android memory management system
我的应用程序的目标是它必须 运行 永远没有用户交互。但它失败了很多次,可能是内存相关的问题。根据 Android 文档,如果系统需要内存,Android 首先让用户通过 onTrimMemory() 发出警告。然而,如果 Android 系统需要更多内存,则抛出 OOM(内存不足)异常,应用程序将崩溃。我的应用程序使用带有 Activity 的服务和带有粘性通知的服务 运行s。(这将使服务保持在前台并且不是要杀死的高级目标)下面的代码创建粘性通知。
private void startForegroundService(Context context, String text){
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
text,
NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) context.getSystemService(NOTIFICATION_SERVICE)).createNotificationChannel(channel);
notificationBuilder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
} else {
notificationBuilder = new Notification.Builder(context);
}
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.background_control))
.setContentText(text)
.setContentIntent(pendingIntent);
startForeground(MAIN_NOTIFICATION_ID, notificationBuilder.build());
}
首先,我不明白的部分是内存相关事件没有按顺序进行。例如,如果 Android 需要内存,那么首先应该按顺序 (5, 20, 60, ..) 抛出 onTrimMemory() 级别,如果需要更多则抛出 OOM。但到目前为止,我所经历的不是连续的,它完全是随机的。而且我的应用程序没有发生内存泄漏。我用 Android IDE Profiler 检查了很多次。并且一些测试应用程序不会出现内存问题。这意味着我认为可能没有内存泄漏。
其次我想知道如何准确估计内存。我现在正在使用 Runtime.getRuntime() 检查当前内存。不仅是App的堆内存,还有系统。我在崩溃发生时记录,但内存已经足够了。下面的代码用于在事件发生时进行记录。
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
Runtime runtime = Runtime.getRuntime();
long totalMem = runtime.totalMemory();
long freeMem = runtime.freeMemory();
final double usedMemInMB = (double) (totalMem - freeMem) / 1048576;
LogManager.addLog(LogManager.WARNING_TAG,
"onTrimMemory Level(" + level + "), Free/ Used/ Total/ Avail: "
+ String.format("%5.2f", (freeMem / 1024.0 / 1024.0)) + "/ "
+ String.format("%5.2f", usedMemInMB) + "/ "
+ String.format("%5.2f", (totalMem / 1024.0 / 1024.0)) + "/ "
+ String.format("%7.2f", (getAvailableMemory() / 1024.0 / 1024.0)) + "MB"
);
}
private long getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo.availMem;
}
所以我不明白为什么 Android 抛出 onTrimMemory() 或 OOM 甚至在没有警告的情况下杀死我的应用程序。
我的应用程序中只有一个内存泄漏问题已解决。
如果有人遇到这个问题,我建议使用 Android Studio 的 Profiler 和 tack 来查找泄漏的位置。
我的应用程序的目标是它必须 运行 永远没有用户交互。但它失败了很多次,可能是内存相关的问题。根据 Android 文档,如果系统需要内存,Android 首先让用户通过 onTrimMemory() 发出警告。然而,如果 Android 系统需要更多内存,则抛出 OOM(内存不足)异常,应用程序将崩溃。我的应用程序使用带有 Activity 的服务和带有粘性通知的服务 运行s。(这将使服务保持在前台并且不是要杀死的高级目标)下面的代码创建粘性通知。
private void startForegroundService(Context context, String text){
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
text,
NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) context.getSystemService(NOTIFICATION_SERVICE)).createNotificationChannel(channel);
notificationBuilder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
} else {
notificationBuilder = new Notification.Builder(context);
}
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.background_control))
.setContentText(text)
.setContentIntent(pendingIntent);
startForeground(MAIN_NOTIFICATION_ID, notificationBuilder.build());
}
首先,我不明白的部分是内存相关事件没有按顺序进行。例如,如果 Android 需要内存,那么首先应该按顺序 (5, 20, 60, ..) 抛出 onTrimMemory() 级别,如果需要更多则抛出 OOM。但到目前为止,我所经历的不是连续的,它完全是随机的。而且我的应用程序没有发生内存泄漏。我用 Android IDE Profiler 检查了很多次。并且一些测试应用程序不会出现内存问题。这意味着我认为可能没有内存泄漏。
其次我想知道如何准确估计内存。我现在正在使用 Runtime.getRuntime() 检查当前内存。不仅是App的堆内存,还有系统。我在崩溃发生时记录,但内存已经足够了。下面的代码用于在事件发生时进行记录。
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
Runtime runtime = Runtime.getRuntime();
long totalMem = runtime.totalMemory();
long freeMem = runtime.freeMemory();
final double usedMemInMB = (double) (totalMem - freeMem) / 1048576;
LogManager.addLog(LogManager.WARNING_TAG,
"onTrimMemory Level(" + level + "), Free/ Used/ Total/ Avail: "
+ String.format("%5.2f", (freeMem / 1024.0 / 1024.0)) + "/ "
+ String.format("%5.2f", usedMemInMB) + "/ "
+ String.format("%5.2f", (totalMem / 1024.0 / 1024.0)) + "/ "
+ String.format("%7.2f", (getAvailableMemory() / 1024.0 / 1024.0)) + "MB"
);
}
private long getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo.availMem;
}
所以我不明白为什么 Android 抛出 onTrimMemory() 或 OOM 甚至在没有警告的情况下杀死我的应用程序。
我的应用程序中只有一个内存泄漏问题已解决。 如果有人遇到这个问题,我建议使用 Android Studio 的 Profiler 和 tack 来查找泄漏的位置。