Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JooFlux at ComPAS 2013

Julien Ponge
January 16, 2013

JooFlux at ComPAS 2013

Julien Ponge

January 16, 2013
Tweet

More Decks by Julien Ponge

Other Decks in Research

Transcript

  1. Julien Ponge Frédéric Le Mouël
    JooFlux
    ComPAS 2013

    View Slide

  2. Objectifs
    JVM, invokedynamic
    Implémentation
    Évaluation
    Conclusions

    View Slide

  3. “Modification de code à chaud et
    injection d’aspects directement
    dans une JVM 7”

    View Slide

  4. (démo)

    View Slide

  5. AspectJ [Kiczales et al., 2001, CACM]
    Byteman [Dinn, 2011, AOSD]
    Steamloom [Bockisch et al., 2004, AOSD]
    JnVM [Thomas et al., 2008, SP+E]
    JVolve [Subramanian et al., 2009, PLDI]
    SafeWeave [Würthinger et al., 2011, OOPSLA]
    Outils
    VMs ad-hoc
    Travaux connexes

    View Slide

  6. Pas de langage d’aspects
    Pas de pré/post compilation
    Un agent Java
    JVM non-modifiée
    JooFlux
    Dév appli
    Runtime

    View Slide

  7. JVM, invokedynamic

    View Slide

  8. Machine à pile
    OpCodes
    invocation de méthode
    manipulation de pile
    get / set champs
    arithmétique
    allocation
    sauts
    lock
    (...)
    Constant pool
    (nombres, String, types)
    0 java/lang/String
    1 “Foo”
    2 666
    ... ...
    Variables locales
    0 this (sauf static)
    1 arg1
    2 arg2
    3 int i
    ... ...

    View Slide

  9. invokestatic
    public static int add(int a, int b)
    invokevirtual
    public int add(int a, int b)
    invokeinterface
    int add(int a, int b)
    invokespecial
    private int add(int a, int b)

    View Slide

  10. Object call (Object receiver, Object[] args) throws Throwable;
    Object call (Object receiver) throws Throwable;
    Object call (Object receiver, Object arg1) throws Throwable;
    Object call (Object receiver, Object arg1, Object arg2) throws Throwable;
    Object call (Object receiver, Object arg1, Object arg2, Object arg3) throws Throwable;
    Object call (Object receiver, Object arg1, Object arg2, Object arg3, Object arg4) throws Throwable;
    Object callConstructor (Object receiver, Object [] args) throws Throwable;
    Object callConstructor (Object receiver) throws Throwable;
    Object callConstructor (Object receiver, Object arg1) throws Throwable;
    Object callConstructor (Object receiver, Object arg1, Object arg2) throws Throwable;
    Object callConstructor (Object receiver, Object arg1, Object arg2, Object arg3) throws Throwable;
    Object callConstructor (Object receiver, Object arg1, Object arg2, Object arg3, Object arg4) throws Throwable;
    Comment résoudre à l’exécution ?
    (extrait de Groovy)

    View Slide

  11. public Object call(Object receiver, Object[] args) throws Throwable {
    return CallSiteArray.defaultCall(this, receiver, args);
    }
    public Object call(Object receiver) throws Throwable {
    return call(receiver, CallSiteArray.NOPARAM);
    }
    public Object call(Object receiver, Object arg1) throws Throwable {
    return call(receiver, ArrayUtil.createArray(arg1));
    }
    public Object call(Object receiver, Object arg1, Object arg2) throws Throwable {
    return call(receiver, ArrayUtil.createArray(arg1, arg2));
    }
    public Object call(Object receiver, Object arg1, Object arg2, Object arg3) throws Throwable {
    return call(receiver, ArrayUtil.createArray(arg1, arg2, arg3));
    }
    public Object call(Object receiver, Object arg1, Object arg2, Object arg3, Object arg4) throws Throwable {
    return call(receiver, ArrayUtil.createArray(arg1, arg2, arg3, arg4));
    }
    “Tous les chemins mènent à Rome”

    View Slide

  12. public static Object invoke(Object object, String methodName, Object[] parameters) {
    try {
    Class[] classTypes = new Class[parameters.length];
    for (int i = 0; i < classTypes.length; i++) {
    classTypes[i] = parameters[i].getClass();
    }
    Method method = object.getClass().getMethod(methodName, classTypes);
    return method.invoke(object, parameters);
    } catch (Throwable t) {
    return InvokerHelper.invokeMethod(object, methodName, parameters);
    }
    }
    Difficile pour le JIT !
    CallSites génériques
    Réflexivité

    View Slide

  13. invokedynamic
    nom symbolique
    + signature
    + bootstrap CallSite
    Constant
    Mutable
    Volatile
    MethodHandle
    direct ou combinateurs
    branchements
    adaptation
    filtres
    (...)
    7

    View Slide

  14. Implémentation

    View Slide

  15. 1
    2
    3
    4
    Chargement des classes
    Interception
    Management
    Runtime

    View Slide

  16. (...)
    ldc #3
    ldc #5
    invokedynamic foo (II)I
    bootstraper
    (...)
    Call site
    JMX agent
    JooFlux
    bootstraper
    Modified bytecode
    Registry
    Target
    method
    combinators Load time action
    Run time action
    Original bytecode
    JVM agent
    1
    2
    3 4

    View Slide

  17. Réécriture de bytecode
    ASM + Agent
    Bootstrap JooFlux
    Casse la vérification de bytecode !
    1

    View Slide

  18. sémantique champ volatile
    impact mesuré négligeable
    VolatileCallSite 2

    View Slide

  19. invokestatic
    invokespecial
    Method handle direct
    invokevirtual
    invokeinterface
    Method handle sur
    le premier receveur
    3

    View Slide

  20. invokeinterface Polymorphic inline-cache
    guardWithTest(Class1, obj)
    guardWithTest(Class2, obj)
    fallback(callsite, args[])
    Class1#foo(II)I
    Class2#foo(II)I
    obj.foo(1, 2)
    3

    View Slide

  21. 4
    public interface JooFluxManagementMXBean {
    public String getName();
    public int getNumberOfRegisteredCallSites();
    public Set getRegisteredCallSiteKeys();
    public String getCallSiteType(String target);
    public void changeCallSiteTarget(String methodType,
    String oldTarget, String newTarget);
    public void applyBeforeAspect(String callSitesKey,
    String aspectClass, String aspectMethod);
    public void applyAfterAspect(String callSitesKey,
    String aspectClass, String aspectMethod);
    }

    View Slide

  22. (...)
    ldc #3
    ldc #5
    invokedynamic foo (II)I
    bootstraper
    (...)
    Call site
    JMX agent
    JooFlux
    bootstraper
    Modified bytecode
    Registry
    Target
    method
    combinators Load time action
    Run time action
    Original bytecode
    JVM agent
    4
    Registre : 0 impact perfs
    Enregistré à la 1ère interception
    Modification via API

    View Slide

  23. Évaluation

    View Slide

  24. Interception / redirection
    de méthode
    Injection d’aspect ‘vide’
    Langages dynamiques
    Plates-formes
    AOP
    Micro
    Fibonacci(40)
    Macro
    SCImark
    Fork/Join
    Clojure
    Benchmarks
    X
    V V
    V

    View Slide

  25. 0
    2
    4
    6
    8
    Byteman Jooflux
    Avant Après Avant + Après
    Injection d’aspect ‘vide’
    x 137
    x 134
    x 306
    x 6
    x 2
    x 5
    Microbench

    View Slide

  26. Interception/redirection méthode
    0
    5
    10
    15
    Clojure JRuby Groovy Rhino JS Jython Java+JooFlux
    Min Max
    x 1
    x 48
    x 18
    x 15
    x 2,2
    x 10
    x 3
    x 6
    x 1,2
    x 2
    Microbench

    View Slide

  27. Interception/redirection méthode
    0.9
    1
    1.1
    SCIMark Fork/Join Clojure
    Min Max
    x 0,99
    x 0,97
    x 1,04
    x 0,93
    x 1,01
    x 1,01
    Macrobench

    View Slide

  28. Conclusion

    View Slide

  29. JVM généraliste
    Interception à grain fin
    Résultats initiaux encourageants
    Approche nouvelle, générique, sans langage dédié
    Bilan

    View Slide

  30. Injection atomique multi-aspects
    Rollback / versioning
    Vérification formelle pré-injection
    Aspects contextuels / Internet of Things
    Contrôle de ressources avec isolation adaptative
    Perspectives

    View Slide

  31. https://github.com/dynamid/jooflux
    Questions / réponses
    Julien Ponge Frédéric Le Mouël
    http://dynamid.citi-lab.fr/

    View Slide