簡體   English   中英

為什么在將一堆數據插入 SQL 時,PhoneGap Android 應用程序崩潰?

[英]Why is PhoneGap Android app crashing while inserting bunch of data into SQL?

我有在 Android 中運行的 PhoneGap 應用程序。 當應用程序啟動時,它會在 SQL 中插入大約 500 行。 表有 10 列。 這不是很多數據,我在文本文件中有一個 JSON,它的大小約為 120 kB。 我認為這根本無法觸及任何限制,但可能存在一些我不知道的限制,或者 Android 中的錯誤,因為同樣的應用程序在 Android(2.2)的某些版本上運行沒有問題,但立即崩潰或者在使用 SQL 數據庫在其他版本的 Android (1.6、2.1、一些 2.3 可能更多......)

這是我用來填充在 Android 1.6 上崩潰的數據庫的代碼:

db = window.openDatabase("db", "1.0", "Description", 1000000); 
$.get('db/app_data.dat',function(result){
  var data = $.parseJSON(result);
  try {
    db.transaction(function(tx){
      $.each(data.items, function(i, v){
        try {
          tx.executeSql('INSERT INTO table(c1,c2,c3, ...) VALUES (?,?,?, ...)',[v.c1, v.c2, v.c3, ...]);
        } catch(e) {
          alert(e.message);
        }
      });
    });
  } catch(e) {
    alert(e.message);
    return;
  }
});

有誰能夠幫我? 有什么我不知道的限制嗎? 還是在 SQL 數據庫中插入數據時我做錯了什么?

編輯:

這是LogCat的output,我認為這些是應用程序崩潰時日志中的一些重要行。 但是,我對 Java 和 Android 沒有更深入的了解:

WARN/dalvikvm(1525): ReferenceTable overflow (max=512)
WARN/dalvikvm(1525): Last 10 entries in JNI local reference table:
WARN/dalvikvm(1525):   502: 0x4375cbb8 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   503: 0x4374c9a0 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   504: 0x4377c5c0 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   505: 0x437c3040 cls=Ljava/lang/String; (36 bytes)
WARN/dalvikvm(1525):   506: 0x43760bd8 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   507: 0x437625e8 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   508: 0x43762608 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   509: 0x43762628 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   510: 0x43759178 cls=Ljava/lang/String; (28 bytes)
WARN/dalvikvm(1525):   511: 0x43766808 cls=Landroid/webkit/WebViewCore; (116 bytes)
ERROR/dalvikvm(1525): Failed adding to JNI local ref table (has 512 entries)
INFO/dalvikvm(1525): "WebViewCoreThread" prio=5 tid=15 RUNNABLE
INFO/dalvikvm(1525):   | group="main" sCount=0 dsCount=0 s=N obj=0x437668a0 self=0x1b0bd0
INFO/dalvikvm(1525):   | sysTid=1532 nice=0 sched=0/0 handle=1772784
INFO/dalvikvm(1525):   at android.webkit.LoadListener.nativeFinished(Native Method)
INFO/dalvikvm(1525):   at android.webkit.LoadListener.tearDown(LoadListener.java:1076)
INFO/dalvikvm(1525):   at android.webkit.LoadListener.handleEndData(LoadListener.java:642)
INFO/dalvikvm(1525):   at android.webkit.LoadListener.handleMessage(LoadListener.java:203)
INFO/dalvikvm(1525):   at android.os.Handler.dispatchMessage(Handler.java:99)
INFO/dalvikvm(1525):   at android.os.Looper.loop(Looper.java:123)
INFO/dalvikvm(1525):   at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:471)
INFO/dalvikvm(1525):   at java.lang.Thread.run(Thread.java:1060)
ERROR/dalvikvm(1525): VM aborting
DEBUG/Zygote(30): Process 1525 terminated by signal (11)

Phobos 的回答有一些相關信息,但不包括它如何應用於您的問題或如何解決您的特定問題。 I ran into a similar issue while doing some performance testing in android javascript that calls across to java via an object bound into the webview context with addJavascriptInterface. 雖然我沒有明確使用 JNI,但顯然在幕后綁定接口使用 JNI 來編組數據 - 我收到了一個類似於你的錯誤和堆棧跟蹤。 顯然,webDB 或 localStorage 或您在那里所做的任何事情也在幕后使用 JNI。

根據 Phobos 鏈接的信息,當您使用 JNI 時,您可以在 scope 中擁有的引用數量是有限的。 在間接使用 JNI 的 javascript 的情況下,似乎必須根據 javascript scope 保留引用。 查看您的代碼,我不確定您正在做什么以超出限制,但看起來它可能是您在整個事務中進行的調用次數或您的值 arrays 最終擁有超過 512 個元素。 如果您需要保持事務完整性並且您確實有超過 500 次操作,那么您可能會不走運。 但是我懷疑您應該能夠通過重寫代碼以在tx.executeSql調用的 scope 之外構建查詢字符串來找到避免 512 限制的方法。

也許您可以重寫代碼來構建查詢字符串,然后在匿名 function 包裝器中實際調用tx.executeSql 您可能需要構建包含值的字符串,而不是使用'INSERT INTO table() VALUES()',[]語法...正如我上面所說,如果您在事務中有超過 500 個操作,您可能仍然運行遇到麻煩,但值得一試!

PS 作為參考,這是我的代碼的一個版本,它與修復一起崩潰:

var test = function() {
    var a = "a";
    for(i=0;i<1000;i++) {
        boundJavaObj.test(a);
    }
}

test() 崩潰並出現如下錯誤:

03-28 10:57:45.634: W/dalvikvm(21294): ReferenceTable overflow (max=512)

var test2 = function() {
    var a = "a";
    for(i=0;i<1000;i++) {
        (function(){boundJavaObj.test(a);})();
    }
}

test2() 不會崩潰。

也許你需要一個遞歸回調 function 像這樣:

//too many insert statements
var sqlits= ["INSERT INTO ...", .. .. .. ,"INSERT INTO ..."];

function populate(){
    db.transaction(function(tx){
        if(sqlits.length > 0){
            sql=sqlits.shift();
            tx.executeSql(sql);
        }else{
            alert('End');
        }
        return true;
    },function(tx,err){ 
        console.log("SQL Error: "+err); 
    },populate);
};

populate();

好的。 找到了答案。 這是 512 個本地引用的限制。 您需要做的是使用 NewGlobalRef() 將它們轉換為全局引用,或者如果不需要它們,則在創建它們后不久清理局部變量。 然而,將它們更改為全局引用將泄漏 memory。

查看線程以獲取有關此已知問題的更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM