问题
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")
回答1:
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 totrue
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 givenAPK
is to use theaapt.exe
tool. You will find theaapt tool
in thebuild-tools
folder of theAndroid 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---------+
回答2:
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/
回答3:
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
回答4:
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
来源:https://stackoverflow.com/questions/58027762/installing-app-takes-minutes-with-dex2oat-warnings