使用dex2oat警告安装应用程序需要几分钟 [英] Installing app takes minutes with dex2oat warnings

查看:1144
本文介绍了使用dex2oat警告安装应用程序需要几分钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间后,我重新打开了一个Android Studio项目,并且可以像往常一样快速构建,但是现在从Android Studio(3.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.

如果我在安装时打开Logcat设备,我会看到很多这样的东西:

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?

在dex2oat开始这个漫长的过程之前,我可以看到以下日志:

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.gradle的一部分.这是一个多模块项目,但是其他文件非常相似.

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

使用vmSafeMode ="true"时

aapt输出

运行./Library/Android/sdk/build-tools/29.0.2/aapt list -a app-debug.apk时的输出很大,仅粘贴了相关部分:

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")

推荐答案

简介

在设备上在安装时间 (使用

Intro

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

这是 android.googlesource verification_results.cc 方法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;
  }

该:

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

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

很有趣,似乎Google对此有所了解.

is interesting, seems Google know about it, somewhat.

此信息消息也很有趣:

I/dex2oat:大型应用程序,可以通过交换运行.

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

建议 dex2oat已检测到大型应用,并将进行交换(

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).

精简您的应用程序!请参见减小您的应用大小.

Slim down your app! See Reduce your app size.

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

指示应用程序是否希望虚拟机(VM) 在安全模式下运行.默认值为"false".

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

此属性是在API级别8中添加的,其中值为"true" 禁用Dalvik即时(JIT)编译器.

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

此属性已适应于API级别22 ,其中值为"true" 禁用ART提前(AOT)编译器.当vmSafeMode是 设置为true时,将使用以下命令执行此过程 参数:

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)使用 adb shell 的后期手动参数插入:

(3) Late manual argument insertion with adb shell:

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

您的跑步状态:

 /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[]

和:

 /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)删除任务

尝试通过关闭不需要的应用程序(或使用类似

  • 仅构建和部署增量更改
  • 不要重新安装该应用程序.
  • 不要重新启动应用程序.
  • 甚至都不要重新启动活动.
  • 另一种确定是否为给定设置vmSafeMode的方法 APK是要使用aapt.exe工具.您会在aapt tool中找到 Android SDKbuild-tools文件夹,不同之处在于 位置取决于您选择的操作系统.您可能会有几个 安装了不同的版本,并且可以在以下位置找到它:

    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
    

    执行列表命令:

    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---------+
    

    这篇关于使用dex2oat警告安装应用程序需要几分钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆