繁体   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