5

I have re-opened an Android Studio project after quite some time, and I'm seeing fast builds as usual, but now the "Install" step from Android Studio (3.5) is taking minutes, while it used to take seconds.

If I open the device Logcat while installing, I can see a huge amount of these:

W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.onSaveInstanceState(android.os.Bundle)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.onViewCreated(android.view.View, android.os.Bundle)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.onViewModelCreated()
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.removeCancelListener(com.package.base.view.BaseDialog$CancelListener)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.removeDismissListener(com.package.base.view.BaseDialog$DismissListener)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.setChildFragmentInjector(dagger.android.DispatchingAndroidInjector)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.setSharedValue(java.lang.String, java.lang.Object)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseDialog.setViewModelFactory(androidx.lifecycle.ViewModelProvider$Factory)
W/dex2oat: Method processed more than once: dagger.android.AndroidInjector com.package.base.view.BaseDialog.supportFragmentInjector()
I/dex2oat: Explicit concurrent copying GC freed 647(112KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 60us total 250.774ms
I/dex2oat: Explicit concurrent copying GC freed 446(29KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 60us total 252.704ms
I/dex2oat: Explicit concurrent copying GC freed 396(13KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 67us total 257.367ms
I/dex2oat: Explicit concurrent copying GC freed 413(13KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 68us total 258.540ms
I/dex2oat: Explicit concurrent copying GC freed 413(13KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 64us total 253.988ms
I/dex2oat: Explicit concurrent copying GC freed 413(13KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 61us total 258.701ms
I/dex2oat: Explicit concurrent copying GC freed 413(13KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 60us total 255.313ms
I/dex2oat: Explicit concurrent copying GC freed 419(45KB) AllocSpace objects, 0(0B) LOS objects, 32% free, 12MB/18MB, paused 60us total 261.034ms
W/dex2oat: Method processed more than once: void com.package.base.view.BaseFragment.<init>()
W/dex2oat: Method processed more than once: void com.package.base.view.BaseFragment.applyStatusBar(com.package.base.view.BaseFragment$StatusBar)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseFragment.dispatchOnStatusBar()
W/dex2oat: Method processed more than once: void com.package.base.view.BaseFragment.restoreStatusBar(android.app.Activity)
W/dex2oat: Method processed more than once: void com.package.base.view.BaseFragment.saveStatusBar(android.app.Activity)

All methods seem to be processed twice (at least) and the garbage collector seems to be doing a lot of work.

I don't know what happened, but I would love to have this fast as it was - right now developing is impossible. Can anyone help?

Extra info

Before dex2oat starts this very long process, I can see the following logs:

W/dex2oat: Unexpected CPU variant for X86 using defaults: x86
W/dex2oat: Mismatch between dex2oat instruction set features (ISA: X86 Feature string: -ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt) and those of dex2oat executable (ISA: X86 Feature string: ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt) for the command line:
W/dex2oat: /system/bin/dex2oat --zip-fd=8 --zip-location=base.apk --input-vdex-fd=-1 --output-vdex-fd=10 --oat-fd=9 --oat-location=/data/app/com.package-7KbZxh8JQyXUOcSGvv-5hA==/oat/x86/base.odex --instruction-set=x86 --instruction-set-variant=x86 --instruction-set-features=default --runtime-arg -Xms64m --runtime-arg -Xmx512m --compiler-filter=quicken --swap-fd=11 --debuggable --classpath-dir=/data/app/com.package-7KbZxh8JQyXUOcSGvv-5hA== --class-loader-context=PCL[]
I/dex2oat: /system/bin/dex2oat --input-vdex-fd=-1 --output-vdex-fd=10 --compiler-filter=quicken --debuggable --classpath-dir=/data/app/com.package-7KbZxh8JQyXUOcSGvv-5hA== --class-loader-context=PCL[]
I/dex2oat: Large app, accepted running with swap.

Build file

This is part of build.gradle for the app module. This is a multi-module project, but the other files are very similar.

android {

    compileSdkVersion(AndroidBuild.compileSdk)

    defaultConfig {
        applicationId = "com.package"
        minSdkVersion(AndroidBuild.minSdk)
        targetSdkVersion(AndroidBuild.targetSdk)
        versionCode = 7
        versionName = "0.2.0"
        vectorDrawables.useSupportLibrary = true
        renderscriptTargetApi = 24
        renderscriptSupportModeEnabled = true
        multiDexEnabled = true

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArgument("clearPackageData", "true")
    }

    signingConfigs {
        create("release") {
            // signing stuff
        }
    }

    testOptions {
        // execution = "ANDROIDX_TEST_ORCHESTRATOR"
    }

    buildTypes {
        getByName("release") {
            signingConfig = signingConfigs.getByName("release")
            isShrinkResources = true
            isMinifyEnabled = true
            proguardFile(getDefaultProguardFile("proguard-defaults.txt"))
            proguardFile("proguard-rules.pro")
        }
        getByName("debug") {
            versionNameSuffix = "-debug"
            // Hoping that this should speed up builds due to multidexing
            defaultConfig.minSdkVersion(21)
        }
    }

    dataBinding.isEnabled = true
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

aapt output when using vmSafeMode="true"

Output when running ./Library/Android/sdk/build-tools/29.0.2/aapt list -a app-debug.apk is huge, pasting only the relevant part:

E: application (line=57)
  A: android:theme(0x01010000)=@0x7f11014c
  A: android:label(0x01010001)=@0x7f100002
  A: android:icon(0x01010002)=@0x7f0e0001
  A: android:name(0x01010003)="com.package.App" (Raw: "com.package.App")
  A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
  A: android:allowBackup(0x01010280)=(type 0x12)0xffffffff
  A: android:vmSafeMode(0x010102b8)=(type 0x12)0xffffffff
  A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff
  A: android:appComponentFactory(0x0101057a)="androidx.core.app.CoreComponentFactory" (Raw: "androidx.core.app.CoreComponentFactory")
natario
  • 24,954
  • 17
  • 88
  • 158
  • can you put gradle file here? – A Farmanbar Sep 22 '19 at 23:38
  • What phone and android version are you using? Have you tried another phone? – esentsov Sep 23 '19 at 11:29
  • @esentsov Tried with a Nexus 5X API 28 and with emulators. It does not seem to be device specific. – natario Sep 26 '19 at 16:03
  • @Mr.AF if you tell me which part you are interested in, I might paste it or simply answer to you. I can tell that this is a MultiDex enabled app, as described here : https://developer.android.com/studio/build/multidex . – natario Sep 26 '19 at 16:04
  • Inside Android tag – A Farmanbar Sep 26 '19 at 16:22
  • @Mr.AF added in question. – natario Sep 26 '19 at 19:11
  • @natario when do warnings appear? in debug mode or release mode? – A Farmanbar Sep 26 '19 at 20:58
  • @Mr.AF in debug, haven't checked release, but that doesn't matter too much. What I really need is fast debug builds. – natario Sep 26 '19 at 21:15
  • @JonGoodwin thanks for info! My machine has 16GB . What is swapping? What are you suggesting? – natario Sep 26 '19 at 21:21
  • @JonGoodwin if this is what you are referring to, I have the following in gradle properties: `org.gradle.jvmargs=-Xmx3072m`. – natario Sep 26 '19 at 21:33
  • Ah, I just saw you say **"Installing"** while I am talking about **"building"**. The most significant change from **Dalvik** to **ART** is that **Dalvik** is based on Just-in-Time (**JIT**) compilation, while **ART** is based on Ahead-of-Time (**AOT**) compilation, on the device. When you install the new way is to complie on the device. [Dalvik](https://en.wikipedia.org/wiki/Dalvik_(software)) See [Android_Runtime](https://en.wikipedia.org/wiki/Android_Runtime). Your old app may be cluttered with unneeded duplicates *processed more than once*: OR your app is too big – Jon Goodwin Sep 26 '19 at 22:25
  • Can you reproduce this if you import your project on a different computer with a clean Android Studio installation? (Use a VM if you don’t have access to another actual computer. Creating a temp user account on your current computer might also be enough.) – Enselic Sep 27 '19 at 04:03
  • @natario i am researching about your problem. i need to know if you configured ART options ? or did you customized ART utility ? – A Farmanbar Sep 28 '19 at 01:31
  • @natario and your target mobile's android version . – A Farmanbar Sep 28 '19 at 02:30
  • @natario i am close to the problem .if my assumption to be true. – A Farmanbar Sep 28 '19 at 02:34
  • @Mr.AF no ART configuration. compileSdk=29, targetSdk=29, minSdk=18 – natario Sep 28 '19 at 10:28

4 Answers4

2

Intro

On device cache build at install time (using dex2oat) i.e. after the app has been built on your build machine:

dex2oat warnings

This is where the W/dex2oat: Method processed more than once: warnings are coming from in the android.googlesource in the file verification_results.cc method WriterMutexLock mu().

  WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
  auto it = verified_methods_.find(ref);
  if (it != verified_methods_.end()) {
    // TODO: Investigate why are we doing the work again for this method and try to avoid it.
    LOG(WARNING) << "Method processed more than once: " << ref.PrettyMethod();
    if (!Runtime::Current()->UseJitCompilation()) {
      DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size());
      DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size());
    }
    // Delete the new verified method since there was already an existing one registered. It
    // is unsafe to replace the existing one since the JIT may be using it to generate a
    // native GC map.
    delete verified_method;
    return;
  }

The:

// TODO: Investigate why are we doing the work again for this method and try to avoid it.

is interesting, seems Google know about it, somewhat.

This Info message is also interesting:

I/dex2oat: Large app, accepted running with swap.

This suggests the dex2oat has detected a large app, and is going to swap (swapping is VERY slow, RAM copied to storage, and back again).

Fixes

(1) Reduce app size

Slim down your app! See Reduce your app size.

(2) Disable ART

ref1 Create a new minimal …/app/src/debug/AndroidManifest.xml file:

<manifest
 xmlns:android="http://schemas.android.com/apk/res/android"> 
 <application android:vmSafeMode="true" />
</manifest>

ref2 android:vmSafeMode

Indicates whether the app would like the virtual machine (VM) to operate in safe mode. The default value is "false".

This attribute was added in API level 8 where a value of "true" disabled the Dalvik just-in-time (JIT) compiler.

This attribute was adapted in API level 22 where a value of "true" disabled the ART ahead-of-time (AOT) compiler. When vmSafeMode is set to true this process will be executed with the following argument:

(3) Late manual argument insertion with adb shell:

/system/bin/dex2oat ... --compiler-filter=interpret-only

Your running:

 /system/bin/dex2oat --zip-fd=8 --zip-location=base.apk --input-vdex-fd=-1 --output-vdex-fd=10 --oat-fd=9 --oat-location=/data/app/com.package-7KbZxh8JQyXUOcSGvv-5hA==/oat/x86/base.odex --instruction-set=x86 --instruction-set-variant=x86 --instruction-set-features=default --runtime-arg -Xms64m --runtime-arg -Xmx512m --compiler-filter=quicken --swap-fd=11 --debuggable --classpath-dir=/data/app/com.package-7KbZxh8JQyXUOcSGvv-5hA== --class-loader-context=PCL[]

and:

 /system/bin/dex2oat --input-vdex-fd=-1 --output-vdex-fd=10 --compiler-filter=quicken --debuggable --classpath-dir=/data/app/com.package-7KbZxh8JQyXUOcSGvv-5hA== --class-loader-context=PCL[]

(4) Remove tasks

Try to maximise your available RAM at install time by closing unneeded apps (or use something like Greenify).

(5) Try useing Instant run

  • Build and deploy only the incremental changes
  • Don’t reinstall the app.
  • Don’t restart the app.
  • Don’t even restart the Activity.

Debugging

Another method for determining if vmSafeMode is set for a given APK is to use the aapt.exe tool. You will find the aapt tool in the build-tools folder of the Android SDK, which differs in location based on your chosen OS. You will probably have several different versions installed and will find it in a location such as:

.../Android/sdk/build-tools/22.0.1/aapt.exe

Execute the list command:

aapt list -a myapkfile.apk

This should produce output including:

Android manifest:
N: android=http://schemas.android.com/apk/res/android
  E: manifest (line=17)
    A: android:versionCode(0x0101021b)=(type 0x10)0x1
    A: android:versionName(0x0101021c)="1.0" (Raw: "1.0")
    A: package="com.testing.sample.myapp" (Raw: "com.testing.sample.myapp")
    A: platformBuildVersionCode=(type 0x10)0x16 (Raw: "22")         <---NOTE
    A: platformBuildVersionName="5.1.1-1819727" (Raw: "5.1.1-1819727")
    E: uses-sdk (line=22)
      A: android:minSdkVersion(0x0101020c)=(type 0x10)0x15
      A: android:targetSdkVersion(0x01010270)=(type 0x10)0x16
    E: application (line=26)
      A: android:label(0x01010001)=@0x7f0b0001
      A: android:icon(0x01010002)=@0x7f030000
      A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
      A: android:vmSafeMode(0x010102b8)=(type 0x12)0xffffffff
                       ^
                       |
----------NOTE---------+
Jon Goodwin
  • 9,053
  • 5
  • 35
  • 54
  • I can't reduce my app size - shrinkers and other optimizations act on release builds, but my issue is during development, on debug builds. I'd like to disable dex2oat on debug builds, but the flag to do so is not working for me https://stackoverflow.com/a/58116259/4288782 . – natario Sep 27 '19 at 21:48
  • @natario It would be helpful if you included the result of **aapt list -a** *myapkfile.apk* (See my debugging update). – Jon Goodwin Sep 27 '19 at 23:01
  • Added to my question. The vmSafeMode is present, but dex2oat still runs (with swapping, warnings, delay and everything). As if it wasn't set. – natario Sep 28 '19 at 10:39
  • @natario The **A: platformBuildVersionCode** =(type 0x10)0x16 (Raw: "22") would be useful along with the values of *AndroidBuild.minSdk* and *AndroidBuild.targetSdk* and *compileSdkVersion(AndroidBuild.compileSdk)* in your **build.gradle**. Presumably your using **apply plugin: 'com.android.application'** and not *apply plugin: 'com.android.dynamic-feature'* Have you updated to the *latest* versions of gradle and Android Studio ? What is your phone API ? – Jon Goodwin Sep 28 '19 at 12:17
  • compileSdk=29, targetSdk=29, minSdk=18, Android Studio 3.5, device API is 27 but this does not seem to be device specific. I am using com.android.application indeed. – natario Sep 29 '19 at 10:35
  • A: platformBuildVersionCode=(type 0x10)0x1d, A: platformBuildVersionName=(type 0x10)0xa – natario Sep 29 '19 at 10:36
  • That is strange @natario, it should work.See from [issuetracker.google.com](https://issuetracker.google.com/issues/123331468) **That either means the app needs to be overall small, or you may consider [splits](https://developer.android.com/studio/build/configure-apk-splits), as they're compiled separately.** Also [issue 77842465](https://issuetracker.google.com/issues/77842465) and [123331468](https://issuetracker.google.com/issues/123331468) – Jon Goodwin Sep 29 '19 at 12:29
  • @natario in case of excessively large resources, put them in a content package. – Martin Zeitler Sep 29 '19 at 12:51
  • I've been able to test vmSafeMode more today. It works on API 24, 25, 26, 28, 29. But on API 27, it has no effect - dex2oat is still running and doing the full job. – natario Sep 29 '19 at 18:41
  • My APK is about 6MB, not a big app really. – natario Sep 29 '19 at 19:33
  • @natari 6MB is small in my opinion. 50-100MB is big. I think it is done on multiple threads, that's why the mutex lock is called so much. Is your Phone short on RAM because you have many services running? – Jon Goodwin Sep 29 '19 at 20:17
  • No, this also happens on a fresh emulator install with basically no apps installed. – natario Sep 30 '19 at 09:46
0

First of all what is dex2oat, it works for Verifying app behavior on the Android runtime (ART) for this refer this link

https://developer.android.com/guide/practices/verifying-apps-art

Now as you need to do is to make this process faster for builds

you can disable this ART(ahead-of-time) to optimize debug deployment and make faster builds. by

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
   ...>

 <application
 ...
 android:vmSafeMode="true">
 ...

Note: it is only possible for targetSdkVersion of 22+ and you’re running a device using the ART runtime.

after disabling this it will decrease you build time for more you can refere the following link https://androidbycode.wordpress.com/2015/07/03/disable-android-art-ahead-of-time-compilation-to-optimize-debug-deployment/

YuvrajsinhJadeja
  • 1,383
  • 7
  • 23
-1

I have something that can help you if you are using windows open up terminal window in android studio and type

gradlew installDebug

or in linux put

./gradlew installDebug 

for more info link here

https://developer.android.com/studio/build/building-cmdline

raj kavadia
  • 926
  • 1
  • 10
  • 30
-1

Below adjustments could make things faster (I have 8Go ram, adapt to yours):

In ..\android-studio\bin\studio64.exe.vmoptions

-Xms2G
-Xmx4G
-XX:ReservedCodeCacheSize=580m
-XX:MetaspaceSize=512m

In studio.exe.vmoptions

-server
-Xms1G
-Xmx2G
-XX:ReservedCodeCacheSize=480m
Chronoslog
  • 107
  • 8