{"record":{"id":"217fe6fe33eee33d","repo":"asLody/VirtualApp","slug":"dex2oat-is-interrupted-msg-e-getmessage","errorCode":null,"errorMessage":"dex2oat is interrupted, msg: ${e.getMessage()}","messagePattern":"dex2oat is interrupted, msg: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/helper/ArtDexOptimizer.java","lineNumber":62,"sourceCode":"        commandAndParams.add(\"--instruction-set=\" + VMRuntime.getCurrentInstructionSet.call());\n        if (Build.VERSION.SDK_INT > 25) {\n            commandAndParams.add(\"--compiler-filter=quicken\");\n        } else {\n            commandAndParams.add(\"--compiler-filter=interpret-only\");\n        }\n\n        final ProcessBuilder pb = new ProcessBuilder(commandAndParams);\n        pb.redirectErrorStream(true);\n        final Process dex2oatProcess = pb.start();\n        StreamConsumer.consumeInputStream(dex2oatProcess.getInputStream());\n        StreamConsumer.consumeInputStream(dex2oatProcess.getErrorStream());\n        try {\n            final int ret = dex2oatProcess.waitFor();\n            if (ret != 0) {\n                throw new IOException(\"dex2oat works unsuccessfully, exit code: \" + ret);\n            }\n        } catch (InterruptedException e) {\n            throw new IOException(\"dex2oat is interrupted, msg: \" + e.getMessage(), e);\n        }\n    }\n\n    private static class StreamConsumer {\n        static final Executor STREAM_CONSUMER = Executors.newSingleThreadExecutor();\n\n        static void consumeInputStream(final InputStream is) {\n            STREAM_CONSUMER.execute(new Runnable() {\n                @Override\n                public void run() {\n                    if (is == null) {\n                        return;\n                    }\n                    final byte[] buffer = new byte[256];\n                    try {\n                        while ((is.read(buffer)) > 0) {\n                            // To satisfy checkstyle rules.\n                        }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ArtDexOptimizer.java#L44-L80","documentation":"interpretDex2Oat runs the dex2oat binary as a child process to compile an APK's DEX to OAT. If the thread waiting for the process is interrupted, waitFor() throws InterruptedException, which is rethrown as an IOException with this message. It signals the optimization was cancelled mid-run, usually by shutdown or another failure upstream.","triggerScenarios":"Calling ArtDexOptimizer.compileDex/interpretDex2Oat while the calling thread is interrupted (e.g. during executor shutdown, activity destroy, or process teardown), causing dex2oatProcess.waitFor() to throw InterruptedException.","commonSituations":"App closing or virtual process being killed while background compilation is still running; cancelling a parallel optimize task; timeouts implemented by interrupting worker threads.","solutions":["Retry the dex2oat compilation on a non-interrupted thread after verifying shutdown is not in progress","Check for code paths that call Thread.interrupt() on the compiling thread and fix the premature cancellation","Ensure dex2oat runs on a dedicated background thread that is not interrupted during app lifecycle events","Clear the interrupt flag (Thread.interrupted()) only if cancellation is stale, then retry once"],"exampleFix":"// before\ntry {\n    final int ret = dex2oatProcess.waitFor();\n} catch (InterruptedException e) {\n    throw new IOException(\"dex2oat is interrupted, msg: \" + e.getMessage(), e);\n}\n// after\ntry {\n    final int ret = dex2oatProcess.waitFor();\n} catch (InterruptedException e) {\n    if (!shuttingDown) {\n        Thread.currentThread().interrupt();\n        final int ret = dex2oatProcess.waitFor(); // retry on a non-cancelled path\n    } else {\n        throw new IOException(\"dex2oat is interrupted, msg: \" + e.getMessage(), e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"if (Thread.currentThread().isInterrupted()) {\n    // reschedule compilation instead of starting it\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    ArtDexOptimizer.compileDex(...);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"interrupted\")) {\n        Thread.currentThread().interrupt();\n        // retry later or degrade to interpreter mode\n    }\n}","preventionTips":["Run dex2oat on a dedicated long-lived worker thread","Do not interrupt threads during app shutdown without awaiting completion","Treat the IOException-with-'interrupted' message as a cancellation signal"],"tags":["android","process","interruption","dex2oat"],"backgroundTag":"operation-interrupted","analyzedSha":"666fefcb5d3f39cc944001c3457c38ffd6544c87","analyzedAt":"2026-09-09T11:09:01.694Z","contentChangedAt":"2026-09-09T11:09:01.694Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}