What is the best strategy to recover from an error - neglecting the record where error occurs

327 views Asked by At

I am getting a No implementation found for native Ldalvik/system/VMRuntime;.pauseGc Error, below is the logCat.

05-13 22:39:22.538: W/dalvikvm(8350): No implementation found for native Ldalvik/system/VMRuntime;.pauseGc:(Ljava/lang/String;)I
05-13 22:39:22.543: E/MyThread(8350): Pause GC
05-13 22:39:22.543: E/MyThread(8350): java.lang.reflect.InvocationTargetException
05-13 22:39:22.543: E/MyThread(8350): at java.lang.reflect.Method.invokeNative(Native Method)
05-13 22:39:22.543: E/MyThread(8350): at java.lang.reflect.Method.invoke(Method.java:515)
05-13 22:39:22.543: E/MyThread(8350): at android.app.MyThread.pauseGC(MyThread.java:5525)
05-13 22:39:22.543: E/MyThread(8350): at android.app.MyThread.performLaunchActivity(MyThread.java:2324)
05-13 22:39:22.543: E/MyThread(8350): at android.app.MyThread.handleLaunchActivity(MyThread.java:2471)
05-13 22:39:22.543: E/MyThread(8350): at android.app.MyThread.access$900(MyThread.java:175)
05-13 22:39:22.543: E/MyThread(8350): at android.app.MyThread$H.handleMessage(MyThread.java:1308)
05-13 22:39:22.543: E/MyThread(8350): at android.os.Handler.dispatchMessage(Handler.java:102)
05-13 22:39:22.543: E/MyThread(8350): at android.os.Looper.loop(Looper.java:146)
05-13 22:39:22.543: E/MyThread(8350): at android.app.MyThread.main(MyThread.java:5602)
05-13 22:39:22.543: E/MyThread(8350): at java.lang.reflect.Method.invokeNative(Native Method)
05-13 22:39:22.543: E/MyThread(8350): at java.lang.reflect.Method.invoke(Method.java:515)
05-13 22:39:22.543: E/MyThread(8350): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
05-13 22:39:22.543: E/MyThread(8350): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
05-13 22:39:22.543: E/MyThread(8350): at dalvik.system.NativeStart.main(Native Method)
05-13 22:39:22.543: E/MyThread(8350): Caused by: java.lang.UnsatisfiedLinkError: Native method not found: dalvik.system.VMRuntime.pauseGc:(Ljava/lang/String;)I
05-13 22:39:22.543: E/MyThread(8350): at dalvik.system.VMRuntime.pauseGc(Native Method)
05-13 22:39:22.543: E/MyThread(8350): ... 15 more

I searched across various forums, but this bug is related to Samsung 4.4.2 and above updates for a Subset of note devices ( I have two Note devices with same specs and this bug only occurs on one of them)

The idea here is to know what is exactly causing this bug, so that I can change the course of my program to avoid a condition wherein this bug can occur. A credible or an official answer is most sought after and I am putting a bounty of 200 on this question once I get eligible.

In my case this occurs when I am doing a memory intense operation, my knowledge (Naive as it might be) tells me it has got something to do with pausing the GC, would a (manual) call to System.gc resolve things for me?

How to recover from this error? In my loop I am reading from One DB table, Address book and a file one after the other. These read values undergo calculation process and results are stored in a larger DB. These statements are in a while loop, I have put checks in try catch so that if any and not limited to this error occurs. I start from the next iteration of the loop using a continue statement in the catch clause- neglecting the record where crash occurs. However the execution is not guaranteed using this method, as the crash can keep happening forcing the subsequent records to be omitted.

Edit: here is the culprit block of code:

if(FLAG ==1){
    toRead=new File(getApplicationContext().getFilesDir()+"/Reminders/fileone.txt");
}else{
    toRead=new File(getApplicationContext().getFilesDir()+"/Reminders/output.txt");
}

//  copyDirectoryOneLocationToAnotherLocation(new File(getApplicationContext().getFilesDir()+"/Reminders/output.txt"), new File("mnt/sdcard/filecheck.txt"));


FileInputStream fis=new FileInputStream(toRead);
Scanner sc=new Scanner(fis);

String currentLine;
while(sc.hasNextLine()){
    try{
        System.out.println("count in file"+i);

        currentLine=sc.nextLine();
        // TODO = gets concatnated 
        StringTokenizer st=new StringTokenizer(currentLine,"=",false);
        CONTACT_NAME = toTitleCase(st.nextToken());


        if(CONTACT_NAME.contains("'")){
            CONTACT_NAME = CONTACT_NAME.replace("'", "");
        }
        // *********
        String listStr = st.nextToken();
        String cut = listStr.substring(1, listStr.length() - 1);
        String[] array = cut.split(",");

        //      System.out.println("Array is: "+Arrays.toString(array));


        CONTACT_ID = (array[0].trim());
        String dateStr = (array[1].trim());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = format.parse(dateStr);
        java.sql.Date dx = new java.sql.Date(date.getTime());
        Date key = dx;
        dateToInsert = String.valueOf(dx); 

        CONTACT_IMAGE_URI = (array[2].trim());
        if(CONTACT_IMAGE_URI.contains("?typ")){
            CONTACT_IMAGE_URI = CONTACT_IMAGE_URI+"e=normal"; 
        }
        if (isCancelled()) {
            break;
        }
        progress = ("" + Character.toUpperCase(CONTACT_NAME.charAt(0)) + CONTACT_NAME.substring(1) + "\n"+i + " of " + lines + " Contacts"); // Progress displayed here. 
        years = getDiffYear(key);               // For years elapsed
        secon = seconds(key);                   // for seconds elapsed
        min = seconds(key) / 60;                // For minutes elapsed
        hours = getDiffHour(key);// For hours elapsed
        mon = months(String.valueOf(key));      // for months elapsed
        days = daysElapsed(key);                // Days elapsed
        weeks = daysElapsed(key) / 7;           // For weeks

        //===============================================================================================================
        if (dateToInsert.contains("0001-") == true){ //Special Case, we added 0001 to Birthdays Which Have NO Year field. 
            //===========================================================================================================

            dbHelper.insert(dateToInsert, CONTACT_NAME, "","", CONTACT_IMAGE_URI, "", "", "", CONTACT_ID, "", "","1"); // All other fields will be empty, because we don't have a Year. 
            int PRIMARY_ID = dbHelper.getPrimaryId();
            String FOREIGN_KEY = dbHelper.getHighestID(PRIMARY_ID); 


            //=====================================================================================================
            //In this case we are only interested in fetching the year alert for next birthday of this contact -->
            //=====================================================================================================

            intCal.yearsToNotify(years, dateToInsert); 
            int yearsSpecial = intCal.getYearsRegular();
            Date dateYearsReg = intCal.getYearsRegDate();

            dbHelper.insertNotifications(5, convertDate(dateYearsReg), 0, yearsSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert ); 

        }
        //=========================================================================
        //Case when all the Date fields exist and we set up notifications  --->
        //=========================================================================
        else if(dateToInsert != "null" && dateToInsert.contains("0001-") != true){
            dbHelper.insert(dateToInsert, CONTACT_NAME, String.valueOf(days), String.valueOf(hours), CONTACT_IMAGE_URI, String.valueOf(min),String.valueOf(mon), String.valueOf(secon), CONTACT_ID, String.valueOf(weeks), String.valueOf(years),"1");
            int PRIMARY_ID = dbHelper.getPrimaryId(); // Fetch the PrimaryId (_id) of the above inserted row, its the Foreign key for Notification and SpecialNotifications Table. 
            String FOREIGN_KEY = dbHelper.getHighestID(PRIMARY_ID); // Same as above, but fetches the Name field of the last inserted row. 



            //=========================================================================
            //**Database Insertions Notifications Table/ SpecialNotifications Table**
            //=========================================================================



            //=======================================================================================//
            //Regular intervals DB Insertions: 
            //======================================================================================//
            //Notification Types:
            //1 for months
            //2 for weeks
            //3 for days
            //4 for minutes
            //5 for years
            //6 for seconds
            //7 for hours
            //======================================================================================//

            //==============================
            //For Months 
            //==============================
            intCal.monthsNotify(mon, dateToInsert);
            int monSpecial =  intCal.getMonthRegular(); 
            Date dateMonReg = intCal.getMonRegDate(); 


            dbHelper.insertNotifications(1, convertDate(dateMonReg), 0, monSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );


            //===============================
            //For Weeks 
            //===============================
            intCal.weeksToNotify(weeks,dateToInsert); 
            int weekSpecial = intCal.getWeekRegular();
            Date dateWeekReg =intCal.getWeekRegDate(); 

            dbHelper.insertNotifications(2, convertDate(dateWeekReg), 0, weekSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );


            //===============================
            //For Days
            //===============================
            intCal.daysToNotify(days, dateToInsert); 
            int daysSpecial= intCal.getDaysRegular();  
            Date dateDaysReg = intCal.getDaysRegDate(); 
            dbHelper.insertNotifications(3, convertDate(dateDaysReg), 0, daysSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );


            //===============================
            //For minutes
            //===============================
            intCal.minutesToNotify(min,dateToInsert);
            long minutesSpecial= intCal.getMinutesRegular();
            Date dateMinsReg = intCal.getMinutesRegDate(); 
            dbHelper.insertNotifications(4, convertDate(dateMinsReg), 0,(int) minutesSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );
            //==============================
            //For Years
            //==============================
            intCal.yearsToNotify(years, dateToInsert); 
            int yearsSpecial = intCal.getYearsRegular();
            Date dateYearsReg = intCal.getYearsRegDate();
            dbHelper.insertNotifications(5, convertDate(dateYearsReg), 0, yearsSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );
            //=============================
            //For Seconds
            //=============================
            intCal.secondsToNotify(secon, dateToInsert);
            long secondsSpecial= intCal.getSecondsRegular(); 
            Date dateSecondsReg = intCal.getSecondsRegDate(); 
            dbHelper.insertNotifications(6, convertDate(dateSecondsReg), 0, secondsSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );


            //=============================
            //For Hours
            //=============================
            intCal.hoursToNotify(hours, dateToInsert); 
            int hoursSpecial= intCal.getHoursRegular();
            Date dateHoursReg= intCal.getHoursRegDate(); 
            dbHelper.insertNotifications(7, convertDate(dateHoursReg), 0, hoursSpecial,FOREIGN_KEY,PRIMARY_ID,CONTACT_IMAGE_URI,dateToInsert );



            //============================================================================================//
            //Special Intervals
            //============================================================================================//
            //Notification Types:
            //1 for months
            //2 for weeks
            //3 for days
            //4 for minutes
            //5 for years
            //6 for seconds
            //7 for hours
            //For Years


            intCal.specialIntervalYears(years, dateToInsert); 
            int yearsOnceSpecial =intCal.getYearsSpecial();
            Date dateYearsSpecial = intCal.getYearsSpDate(); 
            dbHelper.insertSpecialNotifications(5, convertDate(dateYearsSpecial), yearsOnceSpecial,FOREIGN_KEY,PRIMARY_ID);


            //For Months
            intCal.specialIntervalMonths(mon,dateToInsert); 
            int monthsOnceSpecial= intCal.getMonthsSpecial();
            Date dateMonthsSpecial = intCal.getMonthsSpDate();
            dbHelper.insertSpecialNotifications(1, convertDate(dateMonthsSpecial), monthsOnceSpecial,FOREIGN_KEY,PRIMARY_ID);


            //For Weeks
            intCal.specialIntervalsWeeks(weeks,dateToInsert); 
            int weeksOnceSpecial= intCal.getWeeksSpecial(); 
            Date dateWeeksSpecial = intCal.getWeeksSpDate(); 
            dbHelper.insertSpecialNotifications(2, convertDate(dateWeeksSpecial), weeksOnceSpecial,FOREIGN_KEY,PRIMARY_ID);

            //For Days
            intCal.specialIntervalsDays(days, dateToInsert); 
            int daysOnceSpecial= intCal.getDaysSpecial(); 
            Date dateDaysSpecial = intCal.getDaysSpDate(); 
            dbHelper.insertSpecialNotifications(3, convertDate(dateDaysSpecial), daysOnceSpecial,FOREIGN_KEY,PRIMARY_ID);

            //For Hours
            intCal.specialIntervalsHours(hours,dateToInsert); 
            int hoursOnceSpecial= intCal.getHoursSpecial();  
            Date dateHoursSpecial = intCal.getHoursSpDate(); 
            dbHelper.insertSpecialNotifications(7, convertDate(dateHoursSpecial), hoursOnceSpecial,FOREIGN_KEY,PRIMARY_ID);

            //For Minutes
            intCal.specialIntervalMinutes(min,dateToInsert); 
            long minutesOnceSpecial= intCal.getMinutesSpecial(); 
            Date dateMinutesSpecial= intCal.getMinutesSpDate(); 
            dbHelper.insertSpecialNotifications(4, convertDate(dateMinutesSpecial), (int)minutesOnceSpecial,FOREIGN_KEY,PRIMARY_ID);

            //For Seconds
            intCal.specialIntervalsSeconds(secon,dateToInsert); 
            long secondsOnceSpecial= intCal.getSecondsSpecial(); 
            Date dateSecondsSpecial= intCal.getSecondsSpDate(); 
            dbHelper.insertSpecialNotifications(6, convertDate(dateSecondsSpecial), secondsOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 
        }

        publishProgress(progress);
        Asycdialog.setMax(lines);
        Asycdialog.incrementProgressBy(1);
        i++;
    }catch (Exception e){
        System.out.println("From catch 4"+e);
        continue; 
    }
}

Edit 2:

I am doing the above process inside a try catch wherein I am using transactions to speed up things. I have implemented these transaction snippets at the opening of the try block, where I start the transaction and I end them at the finally block and set them successful at the same place.

2

There are 2 answers

1
kaolick On BEST ANSWER

It seems to be a Samsung specific bug. It has been reported to

So far there does not seem to be a solution except updating your Android version (if I got that right).

5
madlymad On

I would suggest to change the dbHelper.insert to be done inside a transaction this may walk-around the issue.

Although your code works is really slow and memory intensive so it may lead straight to an existing bug or occur only in "stressed" devices.

When you insert data to SQLite this way

 private void execQuery(String tableName,ContentValues val)
 {
    sqliteDb = instance.getWritableDatabase();       
    sqliteDb.insert(tableName, null, val);
    return true;
 }

the android method .insert performs a lot of safe checks and then insert them. This procedure I guess allocates a lot of memory and as I measured before takes a lot more execution time than the creation of transaction and inserting data on that.

String sql = "INSERT INTO table (col1, col2) VALUES (?, ?)";
db.beginTransaction();

SQLiteStatement stmt = db.compileStatement(sql);
for (int i = 0; i < values.size(); i++) {
    stmt.bindString(1, values.get(i).col1);
    stmt.bindString(2, values.get(i).col2);
    stmt.execute();
    stmt.clearBindings();
}

db.setTransactionSuccessful();
db.endTransaction();

Note that transaction should start before first insert and end after last insert not a transaction for each insert.

More about transactions at SO here.

I know that my answer may look too irrelevant to the question but I am quite positive that the error would be avoided that way and also the performance will be much improved. Sometimes is better to change the whole logic instead of handling the error.