Какова наилучшая стратегия восстановления после ошибки - игнорирование записи, в которой произошла ошибка

Я получаю ошибку No implementation found for native Ldalvik/system/VMRuntime;.pauseGc, ниже приведен 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

Я искал на разных форумах, но эта ошибка связана с обновлениями Samsung 4.4.2 и выше для подмножества устройств Note (у меня есть два устройства Note с одинаковыми характеристиками, и эта ошибка возникает только на одном из них)

Идея здесь состоит в том, чтобы узнать, что именно вызывает эту ошибку, чтобы я мог изменить ход своей программы, чтобы избежать условия, при котором эта ошибка может возникнуть. Достоверный или официальный ответ наиболее востребован, и я назначу награду в размере 200 на этот вопрос, как только получу право.

В моем случае это происходит, когда я выполняю операцию с интенсивным использованием памяти, мое знание (каким бы наивным оно ни было) говорит мне, что оно как-то связано с приостановкой сборщика мусора, может ли (manual) вызов System.gc решить проблему для меня?

Как исправить эту ошибку? В моем цикле я читаю из одной таблицы БД, адресной книги и файла один за другим. Эти считанные значения подвергаются процессу расчета, а результаты сохраняются в большей базе данных. Эти операторы находятся в цикле while, я поставил проверки в try catch, чтобы, если any and not limited to возникла эта ошибка. Я начинаю со следующей итерации цикла, используя оператор continue в предложении catch, игнорируя запись, в которой происходит сбой. Однако при использовании этого метода выполнение не гарантируется, так как сбой может продолжаться, заставляя последующие записи быть пропущенными.

Изменить: вот блок кода виновника:

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; 
    }
}

Редактировать 2:

Я выполняю описанный выше процесс внутри try catch, в котором я использую транзакции для ускорения работы. Я реализовал эти фрагменты транзакций при открытии блока try, где я начинаю транзакцию и заканчиваю их в блоке finally и устанавливаю их успешно в том же месте.


person Skynet    schedule 06.12.2014    source источник
comment
Мне нужно немного больше информации здесь. 1. Можно ли повторять ошибку регулярно и в одном и том же месте? 2. Можете ли вы в этом случае использовать Step Through, чтобы найти вызывающий нарушение вызов? Если вы знаете, где он находится, пробовали ли вы просто вставить try catch там, где catch просто «break»?   -  person Lord Windy    schedule 08.12.2014
comment
Дайте мне знать, что требуется   -  person Skynet    schedule 08.12.2014
comment
Извините, я не знал, что ввод просто заставит комментарий уйти. Поэтому я отредактировал информацию в моей оригинальной. РЕДАКТИРОВАТЬ: Кроме того, вместо перерыва поставьте продолжение. Я идиот и предложил не тот.   -  person Lord Windy    schedule 08.12.2014
comment
Шаблон попытки поймать и продолжить просто переходит к следующей итерации цикла - я теряю эту конкретную запись. Приложение, как я объяснил, выполняет интенсивные вычисления и хорошо защищено внутри асинхронной задачи, когда я представляю пользователю диалоговое окно загрузки.   -  person Skynet    schedule 08.12.2014
comment
Предполагая, что когда вы говорите «доходит» до следующей итерации, я предполагаю, что она доходит до следующей записи и вызывается другое исключение? Если это так, игнорируйте это, но вместо «продолжения» можно было бы откатить программу на шаг назад (то есть, если цикл int i = 0; i ‹ thingy; i++, тогда вы могли бы отменить все, что вы сделали до сих пор и в конце i--)? Если это не так, то может потребоваться пройти и попытаться заменить оскорбительный код чем-то функционально эквивалентным. Не могли бы вы опубликовать часть кода или это конфиденциально?   -  person Lord Windy    schedule 08.12.2014
comment
Код не оскорбляет, он отлично работает на других устройствах, я проанализировал память с помощью инструментов DDMS. Эта ошибка возникает до того, как система вызовет System.gc(). Что, однако, не находится под моим контролем, поэтому я подумал об использовании system.gc() вручную, однако это плохая практика программирования и будет невозможно, поскольку я ориентируюсь не только на устройства Note. Даже если я откачу всю операцию, нет гарантии, что я не получу эту ошибку в тот или иной момент - по мере увеличения потребления памяти.   -  person Skynet    schedule 08.12.2014
comment
Код не является конфиденциальным, однако он громоздкий, я могу вставить сюда весь модуль.   -  person Skynet    schedule 08.12.2014
comment
Я чувствую, что код не является виновником в этом случае. Я наблюдал ту же проблему, если вы создаете новый проект по умолчанию без какого-либо нового кода от вас.   -  person Ajay    schedule 12.12.2014


Ответы (2)


Похоже, это конкретная ошибка Samsung. Об этом сообщили

Пока не похоже, что есть решение, кроме обновления версии Android (если я правильно понял).

person kaolick    schedule 08.12.2014
comment
Это все известно, у нас еще нет обновления для устройств Note, и мое приложение сделано и для устройств Note, я проверил ошибку на официальных форумах Samsung, но ответа нет. Плохо, как все было сохранено, и это боль для разработчика. - person Skynet; 08.12.2014

Я бы предложил изменить dbHelper.insert внутри транзакции, это может обойти проблему.

Хотя ваш код работает очень медленно и потребляет много памяти, поэтому он может привести к существующей ошибке или возникать только на «нагруженных» устройствах.

Когда вы вставляете данные в SQLite таким образом

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

метод Android .insert выполняет множество безопасных проверок, а затем вставляет их. Эта процедура, наверное, выделяет много памяти и, как я измерял ранее, занимает гораздо больше времени на выполнение, чем создание транзакции и вставка в нее данных.

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

Обратите внимание, что транзакция должна начинаться до первой вставки и заканчиваться после последней вставки, а не транзакция для каждой вставки.

Подробнее о транзакциях в SO здесь.

Я знаю, что мой ответ может показаться слишком не относящимся к вопросу, но я совершенно уверен, что таким образом можно было бы избежать ошибки, а также значительно повысить производительность. Иногда лучше изменить всю логику вместо обработки ошибки.

person madlymad    schedule 08.12.2014
comment
Привет, приятель, мне очень жаль, что я должен был упомянуть об этом в вопросе. Я уже использую транзакции. Вот почему этот жук доставляет мне ужасные ночи. Я оптимизировал все известные мне способы. Я использую механизм try catch для запуска транзакций при попытке, устанавливая их успешно и завершая их в конце концов. Спасибо за содержательный ответ :) - person Skynet; 08.12.2014
comment
Это слишком грустно. Единственное, что я буду исследовать в вашем коде, это Scanner, поскольку я не привык использовать/видеть его в приложениях для Android. И можно обвинить в выделении памяти. Быстрый поиск показал этот stackoverflow.com/a/24304955/944070. Удачи! - person madlymad; 08.12.2014
comment
Спасибо, приятель, последовал совету, теперь есть только BufferedReader, он еще больше ускорил работу :) - person Skynet; 08.12.2014
comment
Нет, это так, я понятия не имею, как избежать этого сейчас! - person Skynet; 09.12.2014
comment
Не могли бы вы обновить сообщение о том, как улучшился ваш код? Я думаю, это имело бы больше смысла. Также я снова смотрю и начинаю подозревать следующее: publishProgress(progress); Asycdialog.setMax(lines); Asycdialog.incrementProgressBy(1); у вас есть диалог прогресса Dialog для Android? Вы пробовали их комментировать? Просто чтобы убедиться, что он все еще воспроизводит ошибку. [У меня был неудачный опыт с диалогами, хотя это было на другой мобильной платформе, а не на Android] - person madlymad; 13.12.2014