web-dev-qa-db-fra.com

Comment puis-je détecter le runtime Android (Dalvik ou ART)?

Google a ajouté un nouveau ART runtime avec Android 4.4. Comment puis-je déterminer si ART ou Dalvik est le runtime actuel?

36
Chris Lacy

Mise à jour

Au moins, dès juin 2014, Google a publié une documentation officielle sur comment vérifier correctement le runtime en cours d'utilisation :

Vous pouvez vérifier quel runtime est utilisé en appelant System.getProperty ("Java.vm.version"). Si ART est utilisé, la valeur de la propriété est "2.0.0" ou supérieure.

Avec cela, il n'est plus nécessaire de passer par la réflexion et de simplement vérifier la propriété système correspondante:

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

Une façon possible est de lire les SystemProperty respectifs par réflexion.

Échantillon:

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

J'espère que cela t'aides.

31
ozbek

Pour tous ceux qui ont besoin d'une version 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;
}

Ou si vous souhaitez suivre un chemin de code plus proche de ce que le rat de la chaussure a publié,

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

Les documents Android donnent en fait la suggestion suivante:

Vous pouvez vérifier quel runtime est utilisé en appelant System.getProperty ("Java.vm.version"). Si ART est utilisé, la valeur de la propriété est "2.0.0" ou supérieure.

Cela semble exact sur mon Nexus 4 avec ART activé (exécutant Android 4.4.4). Nexus 5 sur Dalvik a renvoyé 1.6.0.

2
wsanville

Je pense que vous devriez pouvoir utiliser System.getProperty avec Java.vm.name comme clé. Dans le JavaDoc, sa valeur est Dalvik, ce qui, espérons-le, est Art ou ART lorsque vous utilisez ce runtime . Ça vaut la peine d'essayer...

1
tilpner

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

puis comparez vm avec "libdvm.so" ou "libart.so" pour vérifier s'il s'agit de Dalvik ou ART.

Référence: https://gitorious.org/cyandreamproject/Android_frameworks_base/commit/4c3f1e9e30948113b47068152027676172743eb1

0
Yong

Une solution simple:

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

Sur mon Android 8.0 (API 26) téléphone, il renvoie Dalvik 2.1.0.

0
Domenico