37 votes

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

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

2 votes

Pourquoi voulez-vous le savoir ? Y a-t-il une différence entre les deux points de vue ?

5 votes

Mon application a des difficultés à fonctionner sous ART mais fonctionne bien avec Dalvik. Je cherche donc un moyen d'informer les utilisateurs qu'ils utilisent un runtime expérimental et qu'ils doivent s'attendre à des problèmes de stabilité jusqu'à ce que j'aie l'occasion de les examiner.

1 votes

Les problèmes de l'application fonctionnant sous ART peuvent être vérifiés en suivant les directives et conseils de cette page : developer.Android.com/guide/pratiques/vérification-apps-art.html

33voto

shoe rat Points 6700

Mise à jour

En tout cas, dès juin 2014, Google a publié une documentation officielle sur comment vérifier correctement le temps d'exécution 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.

Ainsi, il n'est plus nécessaire de passer par la réflexion et il suffit de 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 de procéder est de lire les textes respectifs SystemProperty par la 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 vous aidera.

0 votes

Fonctionne comme un charme ! Merci.

0 votes

Attention toutefois : il n'est pas garanti que le nom de la propriété reste le même. Il a déjà changé : Android.googlesource.com/platform/frameworks/base/+/

0 votes

Les autres réponses à cette question semblent préférables : elles sont à la fois plus faciles à mettre en œuvre et moins sujettes à la casse.

4voto

Joseph Lennox Points 821

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 voulez suivre un chemin de code plus proche de ce que Shoe Rat a posté,

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

2voto

wsanville Points 22066

Le site Docs Android donne 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é (sous Android 4.4.4). Nexus 5 sur Dalvik retourné 1.6.0 .

1voto

Je pense que vous devriez pouvoir utiliser System.getProperty con java.vm.name comme clé. Dans la JavaDoc, sa valeur est Dalvik ce qui, espérons-le, est le cas Art o ART en utilisant cette temps de fonctionnement . Cela vaut la peine d'essayer...

1 votes

Lors de l'exécution d'ART : System.getProperty("java.vm.name") renvoie à Dalvik . System.getProperty("java.specification.name") renvoie à Dalvik Core Library . :(

1 votes

Hm, ça aurait été la façon la plus simple de l'interroger. Peut-être qu'ils ne l'ont pas changé parce que ART n'est pas libéré pourtant...

0 votes

Qu'elle soit publiée ou non, elle doit être détectée, même s'il s'agit d'une version de développement. Même s'il est mis à jour à l'avenir, il ne pourra jamais être considéré comme fiable.

0voto

Yong Points 45

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

puis comparez la vm avec "libdvm.so" ou "libart.so" pour vérifier si c'est Dalvik ou ART.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X