【问题标题】:Android java.lang.OutOfMemoryError only on Samsung devicesAndroid java.lang.OutOfMemoryError 仅适用于三星设备
【发布时间】:2017-09-27 15:58:56
【问题描述】:

我在 Google Play 上有一个应用程序昨天更新了,我开始从 Crashlytics 收到大量报告,其中我的应用程序仅在装有 Android 4.x (4.1.2 - 4.4.4) 的三星设备上崩溃。

异常的痕迹如下:

Fatal Exception: java.lang.RuntimeException: An error occured while executing doInBackground()
       at android.os.AsyncTask$3.done(AsyncTask.java:300)
       at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
       at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
       at java.util.concurrent.FutureTask.run(FutureTask.java:242)
       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:841)
Caused by java.lang.OutOfMemoryError
       at java.util.Arrays.copyOfRange(Arrays.java:2684)
       at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:467)
       at javax.crypto.Cipher.doFinal(Cipher.java:1204)
       at com.ijsoft.cpul.Util.DbMainFunctions.com.ijsoft.cpul.Util.AES256Cipher.decrypt(DbMainFunctions.java:2059)
       at com.ijsoft.cpul.Util.DbMainFunctions.initializeDb(DbMainFunctions.java:94)
       at com.ijsoft.cpul.SplashActivity$InitializeDb.doInBackground$9ecd34e(SplashActivity.java:2095)
       at android.os.AsyncTask$2.call(AsyncTask.java:288)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:841)

在其他情况下,我收到以下跟踪:

Fatal Exception: java.lang.RuntimeException: An error occured while executing doInBackground()
       at android.os.AsyncTask$3.done(AsyncTask.java:299)
       at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
       at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
       at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
       at java.util.concurrent.FutureTask.run(FutureTask.java:137)
       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
       at java.lang.Thread.run(Thread.java:856)
Caused by java.lang.OutOfMemoryError
       at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:91)
       at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:201)
       at com.ijsoft.cpul.Util.DbMainFunctions.initializeDb(DbMainFunctions.java:90)
       at com.ijsoft.cpul.SplashActivity$InitializeDb.doInBackground$9ecd34e(SplashActivity.java:2095)
       at android.os.AsyncTask$2.call(AsyncTask.java:287)
       at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
       at java.util.concurrent.FutureTask.run(FutureTask.java:137)
       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
       at java.lang.Thread.run(Thread.java:856)

我留下了发生错误的部分代码:

AES256Cipher.java

public class AES256Cipher {
    public byte[] decrypt(byte[] textBytes, Context context)
            throws java.io.UnsupportedEncodingException,
            NoSuchAlgorithmException,
            NoSuchPaddingException,
            InvalidKeyException,
            InvalidAlgorithmParameterException,
            IllegalBlockSizeException,
            BadPaddingException {

        byte[] keyBytes = CommonFunctions.md5Package(context).getBytes();
        byte[] ivBytes = new byte[16];
        for (int j = 0; j < keyBytes.length; j+=2) {
            ivBytes[j/2]=keyBytes[31-j];
        }

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
        return cipher.doFinal(textBytes);
    }
}

DbMainFunctions.java

public synchronized static int initializeDb(int release, Context context) {
        int resultCode = 0;
        try {
            // Get the encrypted json file (database) from Assets
            AssetManager am = context.getAssets();
            InputStream is = am.open("assets");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buff = new byte[4096];
            int i;
            while ((i = is.read(buff, 0, buff.length)) > 0) {
                baos.write(buff, 0, i);
            }
            is.close();
            baos.close();
            resultCode = updateDb(baos.toByteArray(), release, context);
            //baos.close();
        } catch (Exception e) {
            Log.e("DbMainFunctions", e.getMessage());
            //e.printStackTrace();
            resultCode = -1;
        }
        return resultCode;
    }

public synchronized static int updateDb(byte[] cipherJson, int release, Context context) {
        int resultCode = 0;
        AES256Cipher aes256;
        try {
            aes256 = new AES256Cipher();
            cipherJson = aes256.decrypt(cipherJson, context);
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
                InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            Log.e("DbMainFuctions", e.getMessage());
            return -2;
        }

     ...
}

此时我的应用程序是从 APK 中包含的 Assets 目录中获取一个使用 AES256 的加密文件(文件名:assets)。然后将文件解密并保存在字节数组中。该文件大小约为 4.4 MB。在 doInBackground() 期间从 AsyncTask 调用 initializeDb() 方法,即前面的所有代码都在 AsyncTask 中执行

【问题讨论】:

    标签: java android arrays aes samsung-mobile


    【解决方案1】:

    这很可能会为您提供OutOfMemoryError,尤其是在 Android 5.0 之前,因为您不一定有 4.4MB 的连续可用内存块。

    我会摆脱加密,因为它不提供安全性(任何人都可以解密您的文件)并且会浪费 CPU、电池和内存。

    至少,停止尝试将整个内容读入内存,并以流式方式解密数据(例如,一次 16KB),将解密后的数据流式传输到输出文件(因为您没有足够的内存来最有可能的情况是这样)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 2023-04-01
      • 2016-01-25
      • 1970-01-01
      相关资源
      最近更新 更多