I have PhoneGap app running in Android. When the app starts, it inserts approximately 500 rows into SQL. Table has 10 columns. It\'s not a lot of data, I have a JSON in text
Maybe you need a recursive callback function like this:
//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();
OK. Found the answer. It's a limit of 512 local references. What you need to do is convert them to global references using NewGlobalRef(), or to clean up the locals shortly after creating them if they're not needed. Changing them to global references will leak memory however.
Check out this thread for more information on this known issue.
Phobos' answer has some pertinent information, but it doesn't include how it applies to your problem or how to fix your specific problem. 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. Although I am not explicitly using JNI, apparently under the covers the bound interface uses JNI to marshall the data across - I was getting an error and stack trace similar to yours. Apparently, webDB or localStorage or whatever you are doing there also uses JNI under the covers.
As per the info that Phobos linked, there is a finite limit to the number of references you can have in scope when you are using JNI. In the case of javascript that indirectly uses JNI, it seems that the references must be kept around based on the javascript scope. Looking at your code, I'm not sure exactly what you are doing to exceed the limit, but it looks like it could be either the number of calls you make in the transaction overall or your values arrays end up having more than 512 elements. If you need to preserve transactional integrity and you really have over 500 operations you might be out of luck. However I suspect that you should be able to find a way to avoid the 512 limit by rewriting your code to build up a query string outside of the scope of the tx.executeSql
call.
Maybe you could rewrite the code to build your query strings and then actually call tx.executeSql
inside an anonymous function wrapper? You probably need to build strings containing the values instead of using the 'INSERT INTO table() VALUES()',[]
syntax... As I said above, if you have more than 500 operations in a transaction, you might still run into trouble, but it would be worth a try!
P.S. For reference, here is a version of my code that was crashing along with the fix:
var test = function() {
var a = "a";
for(i=0;i<1000;i++) {
boundJavaObj.test(a);
}
}
test() crashes with an error like:
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() doesn't crash.