web-dev-qa-db-ja.com

Androidランタイム(DalvikまたはART)を検出するにはどうすればよいですか?

Googleは新しい [〜#〜] art [〜#〜] ランタイムを追加しましたAndroid 4.4。ARTまたはDalvikが現在のランタイムかどうかを判断するにはどうすればよいですか?

36
Chris Lacy

更新

少なくとも2014年6月には、Googleは 使用中の現在のランタイムを正しく検証する方法 :に関する公式ドキュメントをリリースしました。

System.getProperty( "Java.vm.version")を呼び出すことで、使用中のランタイムを確認できます。 ARTが使用されている場合、プロパティの値は「2.0.0」以上です。

これにより、リフレクションを通過して、対応するシステムプロパティを単純に確認する必要がなくなりました。

private boolean getIsArtInUse() {
    final String vmVersion = System.getProperty("Java.vm.version");
    return vmVersion != null && vmVersion.startsWith("2");
}

考えられる方法の1つは、それぞれの SystemProperty をリフレクションで読み取ることです。

サンプル:

package com.example.getcurrentruntimevalue;

import Android.app.Activity;
import Android.os.Bundle;
import Android.widget.TextView;

import Java.lang.reflect.InvocationTargetException;
import Java.lang.reflect.Method;

public class MainActivity extends Activity {
    private static final String SELECT_RUNTIME_PROPERTY = "persist.sys.dalvik.vm.lib";
    private static final String LIB_DALVIK = "libdvm.so";
    private static final String LIB_ART = "libart.so";
    private static final String LIB_ART_D = "libartd.so";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = (TextView)findViewById(R.id.current_runtime_value);
        tv.setText(getCurrentRuntimeValue());
    }

    private CharSequence getCurrentRuntimeValue() {
        try {
            Class<?> systemProperties = Class.forName("Android.os.SystemProperties");
            try {
                Method get = systemProperties.getMethod("get",
                   String.class, String.class);
                if (get == null) {
                    return "WTF?!";
                }
                try {
                    final String value = (String)get.invoke(
                        systemProperties, SELECT_RUNTIME_PROPERTY,
                        /* Assuming default is */"Dalvik");
                    if (LIB_DALVIK.equals(value)) {
                        return "Dalvik";
                    } else if (LIB_ART.equals(value)) {
                        return "ART";
                    } else if (LIB_ART_D.equals(value)) {
                        return "ART debug build";
                    }

                    return value;
                } catch (IllegalAccessException e) {
                    return "IllegalAccessException";
                } catch (IllegalArgumentException e) {
                    return "IllegalArgumentException";
                } catch (InvocationTargetException e) {
                    return "InvocationTargetException";
                }
            } catch (NoSuchMethodException e) {
                return "SystemProperties.get(String key, String def) method is not found";
            }
        } catch (ClassNotFoundException e) {
            return "SystemProperties class is not found";
        }
    }
}

お役に立てれば。

31
ozbek

JNIバージョンが必要な人には:

#include <sys/system_properties.h>

static bool isArtEnabled() {
    char buf[PROP_VALUE_MAX] = {};
    __system_property_get("persist.sys.dalvik.vm.lib.2", buf);
    // This allows libartd.so to be detected as well.
    return strncmp("libart", buf, 6) == 0;
}

または、シューラットが投稿したコードパスに近いコードパスを追跡する場合は、

static bool isArtEnabled(JNIEnv *env)
{
    // Per https://developer.Android.com/guide/practices/verifying-apps-art.html
    // if the result of System.getProperty("Java.vm.version") starts with 2,
    // ART is enabled.

    jclass systemClass = env->FindClass("Java/lang/System");

    if (systemClass == NULL) {
        LOGD("Could not find Java.lang.System.");
        return false;
    }

    jmethodID getProperty = env->GetStaticMethodID(systemClass,
        "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");

    if (getProperty == NULL) {
        LOGD("Could not find Java.lang.System.getProperty(String).");
        return false;
    }

    jstring propertyName = env->NewStringUTF("Java.vm.version");

    jstring jversion = (jstring)env->CallStaticObjectMethod(
        systemClass, getProperty, propertyName);

    if (jversion == NULL) {
        LOGD("Java.lang.System.getProperty('Java.vm.version') did not return a value.");
        return false;
    }

    const char *version = env->GetStringUTFChars(jversion, JNI_FALSE);

    // Lets flip that check around to better bullet proof us.
    // Consider any version which starts with "1." to be Dalvik,
    // and all others to be ART.
    bool isArtEnabled = !(strlen(version) < 2 ||
        strncmp("1.", version, 2) == 0);

    LOGD("Is ART enabled? %d (%s)", isArtEnabled, version);

    env->ReleaseStringUTFChars(jversion, version);

    return isArtEnabled;
}
4
Joseph Lennox

Android docs は、実際に次の提案を示します。

System.getProperty( "Java.vm.version")を呼び出すことで、使用中のランタイムを確認できます。 ARTが使用されている場合、プロパティの値は「2.0.0」以上です。

これは、ARTを有効にしたNexus 4で正確に見えます(Android 4.4.4)を実行しています。DalvikのNexus 5は1.6.0

2
wsanville

Java.vm.nameをキーとして System.getProperty を使用できるはずです。 JavaDocでは、その値はDalvikです。これを使用する場合は、ArtまたはARTになりますruntime。それは試みに値します...

1
tilpner

final String vm = VMRuntime.getRuntime().vmLibrary();

そして、vmを「libdvm.so」または「libart.so」と比較して、DalvikかARTかを確認します。

参照: https://gitorious.org/cyandreamproject/Android_frameworks_base/commit/4c3f1e9e30948113b47068152027676172743eb1

0
Yong

簡単な解決策:

String vm = System.getProperty("Java.vm.name") + " " + System.getProperty("Java.vm.version");

私のAndroid 8.0(API 26)電話では、Dalvik 2.1.0を返します。

0
Domenico