Javascript 为什么PhoneGap Android应用程序在将大量数据插入SQL时崩溃?

Javascript 为什么PhoneGap Android应用程序在将大量数据插入SQL时崩溃?,javascript,android,sql,crash,cordova,Javascript,Android,Sql,Crash,Cordova,我的PhoneGap应用程序在Android上运行。当应用程序启动时,它会在SQL中插入大约500行。表有10列。这不是很多数据,我在文本文件中有一个JSON,它的大小约为120 kB。我认为这不会触及任何限制,但可能存在一些我不知道的限制,或者Android中存在缺陷,因为同一个应用程序在某些版本的Android(2.2)上运行时没有问题,但在其他版本的Android上使用SQL数据库时会立即崩溃或在几分钟内崩溃(1.6,2.1,一些2.3可能更多…) 下面是我用来填充Android 1.6上

我的PhoneGap应用程序在Android上运行。当应用程序启动时,它会在SQL中插入大约500行。表有10列。这不是很多数据,我在文本文件中有一个JSON,它的大小约为120 kB。我认为这不会触及任何限制,但可能存在一些我不知道的限制,或者Android中存在缺陷,因为同一个应用程序在某些版本的Android(2.2)上运行时没有问题,但在其他版本的Android上使用SQL数据库时会立即崩溃或在几分钟内崩溃(1.6,2.1,一些2.3可能更多…)

下面是我用来填充Android 1.6上崩溃的DB的代码:

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的输出,我认为这是应用程序崩溃时日志中的一些重要内容。但是,我对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)

好的。找到了答案。这是512个本地引用的限制。您需要做的是使用NewGlobalRef()将它们转换为全局引用,或者很快清理本地引用 如果不需要,则在创建它们之后。但是,将它们更改为全局引用将泄漏内存


查看thread以了解有关此已知问题的更多信息。

Phobos的回答有一些相关信息,但不包括如何应用于您的问题或如何修复您的特定问题。我在android javascript中进行性能测试时遇到了类似问题,该测试通过绑定到带有addJavascriptInterface的webview上下文。虽然我没有显式使用JNI,但显然在幕后绑定的接口使用JNI来整理数据-我得到了一个与您类似的错误和堆栈跟踪。显然,webDB或localStorage或您正在做的任何事情也在幕后使用JNI

根据Phobos链接的信息,当您使用JNI时,范围内的引用数量是有限的。对于间接使用JNI的javascript,似乎必须根据javascript范围保留引用。查看您的代码,我不确定您到底在做什么以超过limit,但它看起来可能是您在整个事务中进行的调用数,也可能是您的值数组最终超过512个元素。如果您需要保持事务完整性,并且您确实有500多个操作,那么您可能会运气不佳。但是我怀疑您应该能够找到一种避免512 li的方法通过重写代码,在
tx.executeSql
调用的范围之外建立查询字符串

也许您可以重写代码来构建查询字符串,然后在匿名函数包装器中实际调用
tx.executeSql
?您可能需要构建包含值的字符串,而不是使用
“INSERT INTO table()values()”,[]
syntax…正如我前面所说,如果一个事务中有500多个操作,您可能仍然会遇到麻烦,但值得一试

请注意,以下是我的代码的一个版本,该版本在修复过程中崩溃:

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

test2()不会崩溃。

也许您需要这样一个递归回调函数:

//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();

来自崩溃的logcat或堆栈跟踪肯定会有帮助。但我认为问题可能有所不同。如果这是在UI线程上运行的,而不是在它自己的线程中运行,系统可能会认为你的应用程序已经停止响应并终止它。好的,我添加了logcat的输出,希望它能帮助解决这个问题。当这个特定的数据ase被设置为包含512个条目。我相信你是一个非常常见的编程错误的受害者。512个条目的条目行将从0到511。我想你是从1开始的。我不能从你的代码中判断,但你的日志显示你的数据库运行过了。嗯,我肯定在创建表时没有设置任何限制。我只是t在我粘贴到这里的代码之前运行这个命令。tx.executeSql('CREATE TABLE_name(id INTEGER,name,time INT,…))@Frodik您有没有遇到过解决方案或修复方法?谢谢,但是在我的代码中我没有创建任何变量,所以我不知道应该怎么做。您的回答没有太大帮助,主要是因为我在Phonegap中使用Javascript,而不是Java本身(在您的示例和链接中使用Java)
//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();