SimpleDateFormat.format()引起的引用表溢出

时间:2015-04-26 07:24:36

标签: java android

我有一个Android项目,并且需要在屏幕上显示当前时间的活动。所以我使用了一个工作线程,每秒一次将消息发布到主线程处理程序中。在处理程序中,我格式化当前时间并在UI上显示它。但是每运行30分钟后我得到一个参考表溢出问题,我的程序因错误而崩溃了。这是日志:

ReferenceTable overflow (max=1024)
JNI pinned array reference table (0x6080b458) dump:
  Last 10 entries (of 1024):
     1023: 0x423b76d0 int[] (1 elements)
     1022: 0x4209cea0 int[] (1 elements)
     1021: 0x4209c890 int[] (1 elements)
     1020: 0x42242198 int[] (1 elements)
     1019: 0x421b7b60 int[] (1 elements)
     1018: 0x420c0e08 int[] (1 elements)
     1017: 0x42107c18 int[] (1 elements)
     1016: 0x421078e8 byte[] (1 elements)
     1015: 0x42116a18 int[] (1 elements)
     1014: 0x42116408 int[] (1 elements)
  Summary:
        1 of byte[] (1 elements)
     1023 of int[] (1 elements) (1023 unique instances)
Failed adding to JNI pinned array ref table (1024 entries)
"main" prio=5 tid=1 RUNNABLE
  | group="main" sCount=0 dsCount=0 obj=0x417f5de0 self=0x417e44a8
  | sysTid=7820 nice=0 sched=0/0 cgrp=apps handle=1074331988
  | state=R schedstat=( 0 0 0 ) utm=972 stm=228 core=0
  at libcore.icu.NativeDecimalFormat.formatLong(Native Method)
  at libcore.icu.NativeDecimalFormat.formatLong(NativeDecimalFormat.java:253)
  at java.text.DecimalFormat.format(DecimalFormat.java:684)
  at java.text.NumberFormat.format(NumberFormat.java:299)
  at java.text.DecimalFormat.format(DecimalFormat.java:702)
  at java.text.SimpleDateFormat.appendNumber(SimpleDateFormat.java:785)
  at java.text.SimpleDateFormat.append(SimpleDateFormat.java:676)
  at java.text.SimpleDateFormat.formatImpl(SimpleDateFormat.java:553)
  at java.text.SimpleDateFormat.format(SimpleDateFormat.java:818)
  at java.text.DateFormat.format(DateFormat.java:307)
  at com.tuyou.tsd.launcher.SleepingActivity.updateTime(SleepingActivity.java:206)
  at com.tuyou.tsd.launcher.SleepingActivity.access$1(SleepingActivity.java:204)
  at com.tuyou.tsd.launcher.SleepingActivity$2.handleMessage(SleepingActivity.java:66)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:136)
  at android.app.ActivityThread.main(ActivityThread.java:5146)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
  at dalvik.system.NativeStart.main(Native Method)
VM aborting
Fatal signal 6 (SIGABRT) at 0x00001e8c (code=-6), thread 7820 (com.tuyou.tsd)

我注意到在SimpleDateFormat.format()方法调用中发生了崩溃。通过查看源代码,我发现该方法只是通过

实现
return format(date, new StringBuffer(), new FieldPosition(0)).toString();

所以我想知道StringBuffer和FieldPosition是否可能导致内存泄漏?或者我的程序运行得太快,以至于对象很快就会变得干净,因此在ref表中引起了太多的对象?这是我的工具代码:

public class SleepingActivity extends BaseActivity {
…
private TimeTask mTimeTask = null;
private SimpleDateFormat mDateFormat = new SimpleDateFormat("HH:mm", Locale.CHINA);
private Date mCurrentTime = new Date();
…

private Handler mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case 100:
            updateTime();
            break;
        default:
            super.handleMessage(msg);
        }
    }
};

private void updateTime() {
    mCurrentTime.setTime(System.currentTimeMillis());
    String time = mDateFormat.format(mCurrentTime); // problem happened here!
    if (mTimeView != null) {
        mTimeView.setText(time);
    }
}

private class TimeTask extends Thread {
    private boolean stop;

    @Override
    public void run() {
        Looper.getMainLooper();
        while (!stop) {
            Message msg = Message.obtain(null, 100);
            mHandler.sendMessage(msg);
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
        }
    }   
}
…

}

请帮忙...... Thx。

=============================================== ============ 编辑: 只需尝试找出根本原因,通过注释掉updateTime()中的所有行,运行大约30分钟后。我得到了另一个参考表溢出错误,这似乎与以前不同。

ReferenceTable overflow (max=1024)
JNI pinned array reference table (0x60865460) dump:
  Last 10 entries (of 1024):
     1023: 0x42269d20 int[] (1 elements)
     1022: 0x42269478 int[] (1 elements)
     1021: 0x42262e50 int[] (1 elements)
     1020: 0x42262dc0 int[] (1 elements)
     1019: 0x42262d28 byte[] (1 elements)
     1018: 0x4225d800 int[] (1 elements)
     1017: 0x42258af0 int[] (1 elements)
     1016: 0x42256940 int[] (1 elements)
     1015: 0x422535d0 int[] (1 elements)
     1014: 0x42251390 int[] (1 elements)
  Summary:
        1 of byte[] (1 elements)
     1023 of int[] (1 elements) (1023 unique instances)

Failed adding to JNI pinned array ref table (1024 entries)
"Binder_3" prio=5 tid=24 RUNNABLE
  | group="main" sCount=0 dsCount=0 obj=0x42151ee0 self=0x60ae8008
  | sysTid=5507 nice=0 sched=0/0 cgrp=apps handle=1627171640
  | state=R schedstat=( 0 0 0 ) utm=2 stm=1 core=0
  at android.os.Parcel.nativeEnforceInterface(Native Method)
  at android.os.Parcel.enforceInterface(Parcel.java:451)
  at android.app.ApplicationThreadNative.onTransact(ApplicationThreadNative.java:383)
  at android.os.Binder.execTransact(Binder.java:404)
  at dalvik.system.NativeStart.run(Native Method)
VM aborting

1 个答案:

答案 0 :(得分:0)

我找到了这个问题的根本原因。它与Java方法无关,它是我的JNI函数调用之一,使用

(*env)->ReleaseByteArrayElements(env, buf, buf_char, JNI_ABORT);

分配一个数组,但在使用后没有释放它。因此在运行30分钟后,ref表溢出。添加

{{1}}
问题永远不会再发生了。