What could be causing the PhoneGap Android app to crash when large amounts of data are being inserted into SQL?

I am currently experiencing an issue with my PhoneGap app on Android. Upon startup, the app inserts around 500 rows into an SQL database with a table containing 10 columns. Although this doesn't seem like a large amount of data, I have encountered crashes when working with the SQL database on certain versions of Android (1.6, 2.1, some 2.3.) The JSON file that I use to populate the DB is about 120 kB in size and resides within a text file. The code snippet I utilize for populating the database is causing the crash on 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;
  }
});

I would appreciate any assistance or insights as to why this might be happening. Could there be some unanticipated limitations or bugs in Android that I'm unaware of?

EDIT:

Upon reviewing the LogCat output provided below, it seems that there are warnings related to JNI local reference tables overflowing. Unfortunately, my knowledge of Java and Android is limited, so any guidance on resolving this issue would be greatly appreciated.

...

Answer №1

In the response from Phobos, there is valuable information provided; however, it does not specifically address how it can be applied to resolve your particular issue. I encountered a similar problem during my performance testing in Android using JavaScript that communicates with Java through an object bound in the webview context via addJavascriptInterface. Even though JNI is not explicitly utilized, it seems that the bound interface utilizes JNI internally to transfer data - resulting in errors and stack traces like the ones you have experienced. Evidently, operations such as webDB or localStorage also leverage JNI in their functioning.

According to the insights shared by Phobos, there exists a limitation on the number of references permissible when working with JNI. For JavaScript indirectly utilizing JNI, these references must be maintained based on the scope of the JavaScript functions. After examining your code, determining precisely where the limit is exceeded remains unclear. It might possibly be due to either the total number of transaction calls being made or the arrays of values ending up surpassing 512 elements. If preserving transactional integrity is essential and you have over 500 operations, finding a workaround could be challenging. Nevertheless, adjusting your code to construct a query string externally to the tx.executeSql call may help bypass the 512 limit.

An alternative approach could involve rewriting the code to assemble query strings beforehand and then executing tx.executeSql within an anonymous function wrapper. Instead of relying on the syntax

'INSERT INTO table() VALUES()',[]
, consider building strings containing the values themselves. Although dealing with more than 500 transactions in one go could still present challenges, attempting this adjustment could potentially yield positive outcomes!

P.S. Here's a piece of code that was causing crashes for me and the solution implemented:

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

The execution of test() resulted in an error message 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);})();
    }
}

Executing test2() did not lead to any crashes.

Answer №2

Perhaps a recursive callback approach could be the solution:

//consider using a recursive function like this
var sqlStatements = ["INSERT INTO ...", .. .. .. , "INSERT INTO ..."];

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

processStatements();

Answer №3

Alright, I've discovered the solution. The limit is 512 local references. To resolve this issue, you should either convert them to global references using NewGlobalRef(), or delete the locals shortly after creating them if they're no longer needed. However, be aware that changing them to global references will result in memory leakage.

For further information on this known issue, please refer to this thread.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sending data from PHP to a text file upon clicking a button

I have been struggling with AJAX and despite my efforts to research on Stack Overflow and other online resources, I still can't get it to work. Any help would be greatly appreciated. My issue involves a formatted JSON file that I am able to parse usi ...

Exploring the functionalities of class methods within an Angular export function

Is it possible to utilize a method from an exported function defined in a class file? export function MSALInstanceFactory(): IPublicClientApplication { return new PublicClientApplication({ auth: AzureService.getConfiguration(), <-------- Com ...

Pressing the middle of the screen to access the Camera App on an Android device

I've encountered a situation where I am required to tap the screen to capture a photo on my Samsung Note device. Could someone please offer some guidance on how to execute a single tap in the center of the screen? https://i.sstatic.net/IFR6n.png ...

How can the Header of a get-request for an npm module be modified?

Currently, I am utilizing an npm module to perform an API request: const api_req = require('my-npm-module-that-makes-an-api-request'); However, I am seeking a way to modify the user-agent used for requests generated internally by the npm module ...

How can we activate navigation on a mobile browser?

I am currently working on a small HTML5/JavaScript website designed to be accessed by mobile browsers on devices such as Android and iPhone. I am utilizing the geolocation feature of HTML5 to obtain the user's current location, but my goal is to then ...

Acquiring HTML Element Data with Clojure

As a beginner in the world of web development, I have chosen Clojure as my backend language. I am currently in the process of transitioning my user authentication from frontend to backend, and specifically trying to extract the value from an HTML password ...

The task execution in Android Studio failed due to an exception with the unknown idk-1.8

I have encountered an error while trying to add a jar file to my project. The issue arises with the following message: Execution failed for task ':app:dexDebug'. com.android.ide.common.process.ProcessException: org.gradle.process.internal.Ex ...

Does the layout.tsx file in Next JS only affect the home page, or does it impact all other pages as well?

UPDATE After some troubleshooting, I've come to realize that the issue with my solution in Next JS 13 lies in the structure of the app. Instead of using _app.tsx or _document.tsx, the recommended approach is to utilize the default layout.tsx. Althou ...

Guide to linking 2 tables in Hibernate within a POJO class structure

Greetings! I have created two POJO classes named DutyManager and DMSchedule. Here are the details of my database tables: Table Name, Duty_Manager: Manager_ID, Title, Name, Age ,Address PK=Manager_ID DM_Schedule: Schedule_ID , Manager_ID, From_Date, To ...

Leveraging ng-hide in Angular to show or hide elements based on the state

Is there a way to utilize the ng-hide directive based on the value selected in a dropdown menu? Specifically, I am looking to display #additional-option if option C is chosen from the dropdown list. <div class="form-group"> <label class="co ...

Creating a dynamic content space: A step-by-step guide

Project Overview I'm currently working on a cinema demo website, where I have implemented four movie poster panels displaying the poster image, title, and screening times. These panels are meant to be clickable. My goal is to have an interactive fea ...

Exploring AngularJS Scope Feeds through Looping

Can someone guide me on how to iterate through this data using AngularJS? I'm comfortable with using var_dump in HTML with Laravel, but I need help debugging and looping through this data in Angular. Any suggestions? $scope.feed = result.data; https ...

Optimal data format for a flexible DataGridView

In the development process of a custom UserControl called CustomizedGrid, I have integrated a DataGridView along with some labels to display row information. To establish communication with SQL, I opted for utilizing the Linq To Sql technology as the foun ...

How can UI tests be run in headless mode in Selenium 4 and above?

Selenium recently announced the release of Selenium 4, and they have also mentioned that there will be no support for PhantomJS from Selenium 4 onwards. Does this mean that Selenium no longer supports headless automation, or is there a different method t ...

Passing data between API tests in JavaScript

I'm encountering an issue where I need to create e2e api tests. The goal of the first test is to obtain a token for an unauthorized user, use that token in the method header for the second test to return a token for an authorized user, and then contin ...

Prioritize displaying a group of data before organizing the remaining information by a selected column

Within my table containing three fields - field1, field2, and field3 - the value in field2 can be either 0 or 1. I am attempting to retrieve field1 in such a way that all rows where the value in field2 is 1 are displayed first and ordered by field3. Subse ...

Pattern matching for identifying repeated numeric sequences

I'm struggling to come up with a regular expression to identify patterns of repeated numbers (more than twice) such as: 1111 or a1111 or test4555 Can anyone lend a hand with this, please? ...

Is there a way to display a cradled FAB in a bottom app bar exclusively for one specific fragment?

I have implemented a BottomAppBar in my app and I am looking to display a cradled FloatingActionButton only for a specific fragment. I want the button to appear exclusively in that particular fragment. Within my activity_main.xml file, there is a Frame th ...

Tips for handling the accent mark (diacritic mark)

My primary language is Spanish, which means I use accent marks quite frequently (á, é...). When I need to type them out, I resort to using &aacute;, &eacute;, and so on. However, I'm facing an issue when trying to compare two sentences in m ...

Having trouble reaching an injected dependency beyond the controller method

Can an injected dependency on a controller be accessed outside of it? function clientCreateController(ClientsService, retrieveAddress) { var vm = this; vm.searchCep = searchCep; } function searchCep(cep) { retrieveAddress.find(cep) .success ...