Java 在字符串上失败时出现内存不足错误
我有一个循环,可以循环数十次,用于债务偿还计算器 这个循环所做的许多事情之一就是调用一个名为Java 在字符串上失败时出现内存不足错误,java,android,out-of-memory,Java,Android,Out Of Memory,我有一个循环,可以循环数十次,用于债务偿还计算器 这个循环所做的许多事情之一就是调用一个名为getSpecialPayment private double getSpecialPayment(long debt_id, int month) { int thisMonth = Calendar.getInstance().get(Calendar.MONTH) + 1; Calendar cal = Calendar.getInstance(); cal.set
getSpecialPayment
private double getSpecialPayment(long debt_id, int month) {
int thisMonth = Calendar.getInstance().get(Calendar.MONTH) + 1;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, month + thisMonth);
SimpleDateFormat df = new SimpleDateFormat("MMM yyyy", Locale.ENGLISH);
String sMonth = df.format(cal.getTime());
// Line 884 that fails below
String check_for_special = "SELECT payment FROM special_payments WHERE id = " + debt_id + " and month = '" + sMonth + "' LIMIT 1;";
if (!database.isOpen()) {
open();
}
Cursor c = database.rawQuery(check_for_special, null);
if (c.getCount() == 0) {
c.close();
return 0;
} else {
c.moveToFirst();
double amount = c.getDouble(c.getColumnIndex("payment"));
c.close();
return amount;
}
}
我在构建字符串(查询)的行上获得这个OutOfMemory
stacktracecheck\u for\u special
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.OutOfMemoryError
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
at java.lang.StringBuilder.append(StringBuilder.java:216)
at com.---.---.DebtDataSource.getSpecialPayment(DebtDataSource.java:884)
at com.---.---.DebtDataSource.payoffDebt(DebtDataSource.java:469)
at com.---.---.PlannerFragment$PlannerTask.doInBackground(PlannerFragment.java:156)
at com.---.---.PlannerFragment$PlannerTask.doInBackground(PlannerFragment.java:122)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
... 4 more
我不明白为什么字符串初始化会导致失败;或者这是一个巧合,一个更大的问题在这一点上失败了
编辑:
这张图片是我的堆转储:
您手头有一个更大的问题。由getSpecialPayment
引起的OOM错误是其他地方内存泄漏的症状
一些上下文,这一行在这里
String check_for_special = "SELECT payment FROM special_payments WHERE id = " + debt_id + " and month = '" + sMonth + "' LIMIT 1;";
真的会这样做吗
StringBuilder builder = new StringBuilder("SELECT payment FROM special_payments WHERE id = ");
builder.append(debt_id);
builder.append("and month = '");
builder.append(sMonth);
builder.append(' LIMIT 1;");
这些都被编译掉了,所以如果不逐行查看代码,就看不到它
这告诉你的是,你正在使用太多的内存,而这些内存并没有被回收,当你尝试做一些简单和低内存的事情时,它正在耗尽内存
我建议创建一个堆转储,并尝试查找内存的最大违犯者。同意,另外,请仔细查看此函数中创建的任何对象(称为“几十次”)。例如,CalendarInstance和SimpleDataFormat可以创建一次并重复使用。此外,考虑一个参数化查询,而不是一个字符串(例如)的RAWQu查询,一个只有参数VALYOK的单个查询字符串。我想我必须找到这个,并学习如何使用内存监视器工具。@kicking莴苣我强烈推荐EclipseMat。它真的很容易使用。jmap是我用于堆转储的工具。@JohnVint我安装了android studio,而不是Eclipse。难道没有一个MAT插件你只能为DDMS下载吗?@kicking莴苣你能得到堆转储吗?无论是通过jmap还是其他方式?如果是这种情况,您可以将EclipseMat作为一个独立的应用程序运行,并将Java二进制堆转储作为参数。因此,不需要与android有关联。