LOG8430 : Architecture logicielle et conception avance Yann-Gal - - PowerPoint PPT Presentation

log8430 architecture logicielle et conception avanc e
SMART_READER_LITE
LIVE PREVIEW

LOG8430 : Architecture logicielle et conception avance Yann-Gal - - PowerPoint PPT Presentation

LOG8430 : Architecture logicielle et conception avance Yann-Gal Guhneuc Bibliothques et le chargement de composantes dynamiques (Contributeurs : Guhneuc 2009-2015 ; Khomh 2009-2014 ; Soh 2012-2014) This work is licensed under a


slide-1
SLIDE 1

Yann-Gaël Guéhéneuc

This work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 3.0 Unported License

LOG8430 : Architecture logicielle et conception avancée

Bibliothèques et le chargement de composantes dynamiques

(Contributeurs : Guéhéneuc 2009-2015 ; Khomh 2009-2014 ; Soh 2012-2014)

slide-2
SLIDE 2

2/182

Plan de la séance

Présentation des fiches de lecture Fin du cours sur la qualité des programmes Bibliothèques et le chargement de

composantes dynamiques

slide-3
SLIDE 3

3/182

Plan de la séance

Présentation des fiches de lecture Fin du cours sur la qualité des programmes Bibliothèques et le chargement de

composantes dynamiques

slide-4
SLIDE 4

4/182

Plan de la séance

Présentation des fiches de lecture Fin du cours sur la qualité des

programmes

Bibliothèques et le chargement de

composantes dynamiques

slide-5
SLIDE 5

5/182

Plan de la séance

Présentation des fiches de lecture Fin du cours sur la qualité des programmes Bibliothèques et le chargement de

composantes dynamiques

slide-6
SLIDE 6

6/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-7
SLIDE 7

7/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-8
SLIDE 8

8/182

  • 1. Introduction

Aucun logiciel de grande taille n’est

développé depuis zéro aujourd’hui

– Sauf dans le cas de développement en « salle blanche »

Utilisation de

– « Bouts de code » – Structures + fonctions / Classes + méthodes – Bibliothèques

slide-9
SLIDE 9

9/182

  • 1. Introduction

Utilisation de

– « Bouts de code » – Structures + fonctions / Classes + méthodes – Bibliothèques

Problèmes

– Légaux – Techniques

slide-10
SLIDE 10

10/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-11
SLIDE 11

11/182

  • 2. Bibliothèques et cadriciels

« Bibliothèque [library] logicielle est un ensemble de

fonctions utilitaires, regroupées et mises à disposition afin de pouvoir être utilisées sans avoir à les réécrire » [Wikipedia]

– Plutôt que de coder une procédure courante dans chaque programme en ayant besoin, on rassemble ces procédures dans des bibliothèques – Si un programme a une fonction à remplir et que celle-ci se trouve en bibliothèque, il l'utilisera directement – Les bibliothèques logicielles se distinguent des exécutables dans la mesure où elles ne représentent pas une application – Exemples

  • La bibliothèque de classes Java (!)
  • La STL de C++ (!!)
slide-12
SLIDE 12

12/182

  • 2. Bibliothèques et cadriciels

L'organisation classique des bibliothèques se fait

par découpage thématique des fonctions, suivant les services qu'elles rendent

– Bibliothèques de bas niveau ou bibliothèques système : elles fournissent des services d'interface avec le système d'exploitation, avec les périphériques, ou fournissent des outils génériques

  • Bibliothèques d'entrées/sorties : fonctions de lecture et d'écriture

de fichiers, de périphériques d'entrée/sortie comme le clavier, l'écran, etc.

  • Gestion de structures de données système
slide-13
SLIDE 13

13/182

  • 2. Bibliothèques et cadriciels

– Bibliothèques de haut niveau, aussi appelées bibliothèques métier, elles interagissent avec celles de bas niveau : les fonctions qu'elles contiennent sont propres à une activité spécifique

  • Boîtes à outils graphiques : ensemble de fonctions permettant

de gérer, d'animer et d'afficher des objets graphiques complexes

– OpenGL

  • Bibliothèques d'opérateurs de traitement d'image : ensemble de

fonctions destinées à structurer l'information dans une image à des fins d'analyse

  • Gestion de structures de données utilisateur
slide-14
SLIDE 14

14/182

  • 2. Bibliothèques et cadriciels

Autres bibliothèques

– Combinateurs en programmation fonctionnelle – Protocoles de méta programmation

Les bibliothèques offrent une interface de programmation

(API), permettant aux programmeurs de choisir les fonctions

– API est la « partie visible » d'une bibliothèque ou d'un ensemble de bibliothèques – Les API se présentent comme une liste des noms des fonctions

  • u/et classes disponibles, avec une documentation sur les

paramètres à leur fournir et sur les résultats retournés

slide-15
SLIDE 15

15/182

  • 2. Bibliothèques et cadriciels

« Un cadriciel [framework] est un espace de

travail modulaire. C'est un ensemble de bibliothèques, d'outils et de conventions permettant le développement de programmes.» [Wikipedia]

Un framework fournit

– Un ensemble de fonctions facilitant la création de tout ou d'une partie d'un système logiciel – Un guide architectural en divisant le domaine visé en modules

slide-16
SLIDE 16

16/182

  • 2. Bibliothèques et cadriciels

Un cadriciel fournit un contexte où les composants sont

réutilisés

– Bibliothèque/Library = ensemble des fonctions – Cadriciel/Framework

  • Bibliothèque(s)
  • Architecture logicielle préconisée pour cette bibliothèque (en couche,

suivant MVC)

  • Environnement de développement bâti autour de la bibliothèque

– Exemples

  • La STL de C++
  • JUnit
  • Eclipse Equinox OSGi
slide-17
SLIDE 17

17/182

  • 2. Bibliothèques et cadriciels

On trouve différents types de cadriciels

– Cadriciel d'infrastructure système : pour développer des systèmes d'exploitation, des interfaces graphiques, des outils de communication

  • Framework .Net, Eclipse, NetBeans, Struts

– Cadriciel d'intégration intergicielle (middleware) : pour fédérer des applications hétérogènes. Pour mettre à dispositions différentes technologies sous la forme d'une interface unique

  • Ampoliros avec ses interfaces RPC, SOAP, XML

– Cadriciel d'entreprise : pour développer des applications spécifiques au secteur d'activité de l'entreprise

  • MDAL

– Cadriciel orientés système de gestion de contenu

  • Joomla, itsEasy, WMaker
slide-18
SLIDE 18

18/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-19
SLIDE 19

19/182

Interconnections

Clients–Libraries/Frameworks

– Linking – Forking – Inter-process communication – Subclassing – Dynamic loading/invoking

slide-20
SLIDE 20

20/182

Interconnections

Linking

(Contrast with virtual machines) – Typically C/C++ – Several object files (.o) – One executable (.exe)

slide-21
SLIDE 21

21/182

Interconnections

Forking

– Typical in most languages – Process duplication

  • Is a real duplication
  • Creates a new OS

process

final StringBuffer commandLine = new StringBuffer(); commandLine.append("..\\DOT\\bin\\dotty "); commandLine.append(aFilePath); final Process process = Runtime.getRuntime().exec(commandLine.toString()); final OutputMonitor errorStreamMonitor = new OutputMonitor(...,process.getErrorStream(),...); errorStreamMonitor.start(); final OutputMonitor inputStreamMonitor = new OutputMonitor(...,process.getInputStream(),...); inputStreamMonitor.start(); try { process.waitFor(); } catch (final InterruptedException ie) { ie.printStackTrace( Output.getInstance().errorOutput()); } if (process.exitValue() != 0) { ... }

slide-22
SLIDE 22

22/182

Interconnections

IPC

– Typical in most languages – Use remote procedure calls – Use well-defined protocols

  • COM
  • CORBA
  • XML-RPC

– Web services

slide-23
SLIDE 23

23/182

Interconnections

package kr.ac.yonsei.cse3009.rpc; import java.net.URL; import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; public class Client { public static void main(final String[] args) throws Exception { final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); config.setServerURL( new URL("http://127.0.0.1:8080/xmlrpc")); final XmlRpcClient client = new XmlRpcClient(); client.setConfig(config); final Object[] params = new Object[] { new Integer(33), new Integer(9) }; final Integer result = (Integer) client.execute("Calculator.add", params); System.out.println(result); } } package kr.ac.yonsei.cse3009.rpc; import org.apache.xmlrpc.server.PropertyHandlerMapping; import org.apache.xmlrpc.server.XmlRpcServer; import org.apache.xmlrpc.webserver.WebServer; public class Server { public static void main(final String[] args) throws Exception { final WebServer webServer = new WebServer(8080); final XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer(); final PropertyHandlerMapping phm = new PropertyHandlerMapping(); phm.addHandler("Calculator", Calculator.class); xmlRpcServer.setHandlerMapping(phm); webServer.start(); } } package kr.ac.yonsei.cse3009.rpc; public class Calculator { public int add(final int i1, final int i2) { return i1 + i2; } public int sub(final int i1, final int i2) { return i1 - i2; } }

slide-24
SLIDE 24

24/182

Interconnections

Subclassing

– Typical in most object-

  • riented languages

– Structural, static relation

public class OutputMonitor extends Thread { ... public OutputMonitor(...) { this.setName(threadName); this.setPriority(Thread.MAX_PRIORITY); ... } public void run() { try { int value = 0; byte[] bytes; char lastWrittenChar; while ((value = this.inputStream.read()) > 0) { synchronized (System.err) { synchronized (System.out) { if (value != 13 && value != 10) { lastWrittenChar = (char) value; ... }} } } catch (final IOException ioe) { ...

slide-25
SLIDE 25

25/182

Interconnections

Subclassing

– Hooks and templates

  • Hot spots = hooks
  • Frozen spots = templates

– Hooks are typically abstract methods – Templates typically use hooks

slide-26
SLIDE 26

26/182

Interconnections

Subclassing

– Hooks and templates

  • JUnit
slide-27
SLIDE 27

27/182

Interconnections

Template Hooks

public abstract class TestCase extends Assert implements Test { public void runBare() throws Throwable { setUp(); try { runTest(); } finally { tearDown(); } } protected void setUp() throws Exception { } protected void tearDown() throws Exception { } ... }

slide-28
SLIDE 28

28/182

Interconnections

Subclassing

– Heavily used in object-oriented programs – Heavily used in design patterns

(Only Singleton does not explicitly use subclassing)

  • Abstract Factory
  • Composite
  • Decorator
  • Observer
  • Visitor
slide-29
SLIDE 29

29/182

Sous-classage

Patrons de conception [Gamma et al.]

– Usine abstraite (Abstract Factory) – Adapteur (Adapter) – Pont (Bridge) – Constructeur (Builder)

slide-30
SLIDE 30

30/182

Sous-classage

Patrons de conception [Gamma et al.]

– Décorateur (Decorator) – Méthode usine (Factory Method) – Itérateur (Iterator) – Observateur (Observer)

slide-31
SLIDE 31

31/182

Sous-classage

Patrons de conception [Gamma et al.]

– Méthode gabarit (Template Method) – Visiteur (Visitor)

slide-32
SLIDE 32

32/182

Interconnections

Dynamic loading

– In different programming languages (but not all), it is the possibility to load, use, and unload a piece of code at runtime – In Java, it is the possibility to load and unload a class and to choose and invoke its methods (and to access its fields…) at runtime

slide-33
SLIDE 33

33/182

Interconnections

Poor man’s profiler

– Calls the main() method of a class whose name is given at runtime, by the user – Displays the time spent in the called method

public final class PoorManProfiler { public static void main(final String[] args) { try { final Class toBeRun = Class.forName(args[0]); final Method mainMethod = toBeRun.getMethod("main", new Class[] { String[].class }); final long startTime = System.currentTimeMillis(); mainMethod.invoke(null, new Object[] { new String[0] }); final long endTime = System.currentTimeMillis(); System.out.println(); System.out.println(endTime - startTime); } catch (final Exception e) { e.printStackTrace(); } } }

slide-34
SLIDE 34

34/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-35
SLIDE 35

35/182

Interconnexions

Problèmes légaux

[Daniel M. German and Ahmed E. Hassan ; License Integration Pattern: Dealing with Licenses Mismatches in Component-based Development ; ICSE, May 2009, ACM Press] – Licences

  • BSD
  • GPL
  • Apache
slide-36
SLIDE 36

36/182

Interconnexions

Problèmes légaux

– Une licence est un ensemble de droits – Chaque droit est un ensemble de conjonctions – Exemple

  • Licence « BSD originale »
  • Droit de « distribuer des produits dérivés en binaire »
  • Conjonctions

– « La redistribution […] doit reproduire la note de droit d’auteur ci-dessus […] » – « Tous les produits publicitaires doivent inclure […] » – « Ni le nom de l’auteur ni ceux des contributeurs […] »

slide-37
SLIDE 37

37/182

Interconnexions

Problèmes légaux

– Soit un programme S composé de deux composants C1 et C2 – S, C1 et C2 ont chacun une licence – Ces licences ne sont compatibles que si leurs droits sont compatibles

slide-38
SLIDE 38

38/182

Interconnexions

Problèmes légaux

– Exemple

  • S est MPL 1.1 et C1 et C2 sont GPL 2
  • GPL 2 stipule que « Tous produits dérivés de C1 (C2)

doit être sous licence GPL 2 »

  • S est MPL 1.1, et MPL 1.1 impose aussi que tout

produit dérivés de S soit sous MPL1.1 ou futures MPL

  • L’intégration de C1 et C2 dans S est impossible
slide-39
SLIDE 39

39/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-40
SLIDE 40

40/182

Chargement dynamique

En deux mots

– Dans différents langage de programmation (Lisp, C++, Java, Smalltalk…), c’est la possibilité de lier un « bout de code » au programme pendant l’exécution du programme – En Java, c’est la possibilité de lier une classe, créer une instance de cette classe et exécuter une de ces méthodes pendant l’exécution du programme

slide-41
SLIDE 41

41/182

Chargement dynamique

Chargeur de classes

– Bootstrap : charge les classes de base et les classes des .jar à l’exécution – Application : charge les classes à partir d’un chemin et les classes de votre application

Les classes chargées

– java -verbose:class MyClass

slide-42
SLIDE 42

42/182

Chargement dynamique

Charger une classe à

partir de son nom

– Classe enveloppante (wrapper)

Appeler une méthode

de la classe

Charger une classe vs.

Chargeur de classe

public final class WrapperMain { public static void main(String[] args) { try { Class toBeRun = Class.forName(args[0]); Method mainMethod = toBeRun.getMethod("main", new Class[] { String[].class }); final long startTime = System.currentTimeMillis(); mainMethod.invoke(null, new Object[] { new String[0] }); final long endTime = System.currentTimeMillis(); System.out.println(); System.out.println(endTime - startTime); } catch (final Exception e) { e.printStackTrace( Output.getInstance().errorOutput()); } } }

slide-43
SLIDE 43

43/182

Reflection

Reflection enables dynamic loading

– Reflection ⇒ dynamic loading – Dynamic loading ⇒ Reflection

  • Think of dynamically-loaded shared libraries in

C-based operating systems, such as AmigaOS, Linux, UN*X, Windows…

slide-44
SLIDE 44

44/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-45
SLIDE 45

45/182

Reflection

Reflection is the ability of a computer

program to examine and modify the structure and behaviour of an object at runtime

slide-46
SLIDE 46

46/182

Scenarios

Scenario 1: invoke an arbitrary method on

an object (see the problems with instanceof and plugins)

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo

slide-47
SLIDE 47

47/182

Scenarios

Scenario 2: access the complete (including

private) state of an object (see the problem with serialisation)

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time

slide-48
SLIDE 48

48/182

Scenarios

Scenario 3: count the number of instances of

a class created at runtime (see the problem with debugging/profiling)

– Given a class C – Record the number of its instances ever created – Report this number when the program ends

slide-49
SLIDE 49

49/182

Scenarios

Scenario 4: patch the method of a class to

change its behaviour (see the problem with patching)

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-50
SLIDE 50

50/182

Scenarios

Java Smalltalk C++

slide-51
SLIDE 51

51/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo public class C { private int i; public C(final int anInt) { this.i = anInt; } public void foo(final String s) { System.out.print(s); System.out.println(this.i); } }

slide-52
SLIDE 52

52/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo Identify all the methods available on o foo getClass hashCode equals toString notify notifyAll wait wait wait Invoke a method using its name foo This is foo: 42

slide-53
SLIDE 53

53/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo final C o = new C(42); System.out.println("Identify all the methods available on o"); final Class<?> classOfO = o.getClass(); final Method[] methodsOfC = classOfO.getMethods(); for (int i = 0; i < methodsOfC.length; i++) { final Method method = methodsOfC[i]; System.out.print('\t'); System.out.println(method.getName()); } System.out.println("Invoke a method using its name foo"); final Method fooMethod = classOfO.getMethod("foo", new Class[] { String.class }); fooMethod.invoke(o, new Object[] { "\tThis is foo: " });

slide-54
SLIDE 54

54/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo Identify all the methods available on o foo getClass hashCode equals toString notify notifyAll wait wait wait Invoke a method using its name foo This is foo: 42

slide-55
SLIDE 55

55/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time public class C { private int i; public C() { this(-1); } public C(final int anInt) { this.i = anInt; } public void foo(final String s) { System.out.print(s); System.out.println(this.i); } }

slide-56
SLIDE 56

56/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time Save on disk the complete state of o i = 42 Restore from disk the object o at a later time This is foo on o2: 43

slide-57
SLIDE 57

57/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time final C o1 = new C(42); System.out.println("Save on disk the complete state of o"); final Class<?> classOfO = o1.getClass(); final Field[] fieldsOfC = classOfO.getDeclaredFields(); for (int i = 0; i < fieldsOfC.length; i++) { final Field field = fieldsOfC[i]; field.setAccessible(true); System.out.print('\t' + field.getName()); System.out.println(" = " + field.getInt(o1)); } System.out.println("Restore from disk the object o at a later time"); final C o2 = (C) classOfO.newInstance(); final Field fieldiOfC = classOfO.getDeclaredField("i"); fieldiOfC.setAccessible(true); fieldiOfC.setInt(o2, 43);

  • 2.foo("\tThis is foo on o2: ");
slide-58
SLIDE 58

58/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time Save on disk the complete state of o i = 42 Restore from disk the object o at a later time This is foo on o2: 43

slide-59
SLIDE 59

59/182

Scenarios

Scenario 3:

– Given a class C – Record the numbers of its instance ever created – Report this number when the program ends public class C { private static int numberOfInstances; public static int getNumberOfInstances() { return C.numberOfInstances; } private int i; public C() { this(-1); } public C(final int anInt) { C.numberOfInstances++; this.i = anInt; } public void foo(final String s) { System.out.print(s); System.out.println(this.i); } }

slide-60
SLIDE 60

60/182

Scenarios

Scenario 3:

kr.ac.yonsei.it.cse3009.reflection.scenario3.C@150bd4d kr.ac.yonsei.it.cse3009.reflection.scenario3.C@1bc4459 kr.ac.yonsei.it.cse3009.reflection.scenario3.C@12b6651 3 – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-61
SLIDE 61

61/182

Scenarios

Scenario 3:

public class Main { public static void main(final String[] args) { final C o1 = new C(42); final C o2 = new C(1); final C o3 = new C(100); System.out.println(o1 + "\n" + o2 + '\n' + o3); System.out.println(C.getNumberOfInstances()); } } – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-62
SLIDE 62

62/182

Scenarios

Scenario 3:

kr.ac.yonsei.it.cse3009.reflection.scenario3.C@150bd4d kr.ac.yonsei.it.cse3009.reflection.scenario3.C@1bc4459 kr.ac.yonsei.it.cse3009.reflection.scenario3.C@12b6651 3

To fulfill this scenario, we must modify C

– Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-63
SLIDE 63

63/182

Scenarios

Class Class is a metaclass

– It describes other classes

Class Method is a class

– It describes methods

Class Field is a class

– It describes fields

slide-64
SLIDE 64

64/182

Scenarios

Class Class is a metaclass

– It allows to reify classes

Class Method is a class

– It allows to reify methods, these language constructs become first-class entities

Class Field is a class

– It allows to reify fields , these language constructs become first-class entities

slide-65
SLIDE 65

65/182

Scenarios

Class Class is a metaclass

– It allows to reify classes

Class Method is a class

– It allows to reify methods, these language constructs become first-class entities

Class Field is a class

– It allows to reify fields, these language constructs become first-class entities

Reification is the process of making available an implicit construct of a language

slide-66
SLIDE 66

66/182

Scenarios

We never modified class Class

– We only used it to obtain the methods and fields declared by particular classes, e.g., C

We used static fields and methods to count

number of instances

slide-67
SLIDE 67

67/182

Scenarios

Scenario 4:

public interface I { public void foo(final String s); } public class C implements I { private int i; public C(final int anInt) { this.i = anInt; } public void foo(final String s) { System.out.print(s); System.out.println(this.i); } } – Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-68
SLIDE 68

68/182

Scenarios

Scenario 4:

This is o: 42 Forwarding method: "foo" Original arguments: "This is o: " New arguments: "THIS IS O: " THIS IS O: 42 – Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-69
SLIDE 69

69/182

Scenarios

Scenario 4:

final I o = new C(42);

  • .foo("This is o: ");

final InvocationHandler handler = new InvokationHandler(o); final I proxy = (I) Proxy.newProxyInstance( I.class.getClassLoader(), new Class[] { I.class }, handler); Assert.assertTrue(proxy instanceof I); Assert.assertFalse(proxy instanceof C); Assert.assertTrue(proxy.equals(o)); proxy.foo("This is o: "); – Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-70
SLIDE 70

70/182

Scenarios

Scenario 4:

public class InvokationHandler implements InvocationHandler { private final I i; public InvokationHandler(final I aConcreteImplementationOfI) { this.i = aConcreteImplementationOfI; } public Object invoke( final Object aProxy, final Method aMethod, final Object[] someArgs) throws Throwable { if (aMethod.getName().equals("foo")) { final String arg = (String) someArgs[0]; final String newArg = arg.toUpperCase(); System.out.print("Forwarding method: \""); System.out.print(aMethod.getName()); System.out.print("\"\n\tOriginal arguments: \""); System.out.print(arg); System.out.print("\"\n\tNew arguments: \""); System.out.print(newArg); System.out.println('\"'); this.i.foo(newArg); return null; } else { return aMethod.invoke(this.i, someArgs); } } } – Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-71
SLIDE 71

71/182

Scenarios

Scenario 4:

final I o = new C(42);

  • .foo("This is o: ");

final InvocationHandler handler = new InvokationHandler(o); final I proxy = (I) Proxy.newProxyInstance( I.class.getClassLoader(), new Class[] { I.class }, handler); Assert.assertTrue(proxy instanceof I); Assert.assertFalse(proxy instanceof C); Assert.assertTrue(proxy.equals(o)); proxy.foo("This is o: ");

Properties of the proxy ensured by the Java VM

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-72
SLIDE 72

72/182

Scenarios

Smalltalk

– Everything is an object – Everything is an object, really

static

slide-73
SLIDE 73

73/182

Scenarios

Smalltalk

– SmalltalkImage is the class that “represent[s] the current image and runtime environment, including system organization, the virtual machine, object memory, plugins, and source

  • files. [Its] instance variable #globals is a

reference to the system dictionary of global variables and class names. [Its] singleton instance is called Smalltalk.”

slide-74
SLIDE 74

74/182

Scenarios

Smalltalk

– Object is “the root class for almost all of the

  • ther classes in the class hierarchy. […] Class

Object provides default behavior common to all normal objects, such as access, copying, comparison, error handling, message sending, and reflection. Also utility messages that all

  • bjects should respond to are defined here.”
slide-75
SLIDE 75

75/182

Scenarios

Smalltalk

– Class “[adds] instance-specific behavior to various class-describing objects in the system. This typically includes messages for initializing class variables and instance creation messages particular to a class. There is only one instance

  • f a particular Metaclass, namely the class

which is being described.”

slide-76
SLIDE 76

76/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo Object subclass: #C instanceVariableNames: 'i' classVariableNames: '' poolDictionaries: '' category: 'CSE3009'. C class compile: 'newWithi: anInt ^(self new) i: anInt ; yourself.'. C compile: 'foo: aText Transcript show: aText. Transcript show: i. Transcript cr.'. C compile: 'i: anInt i := anInt.'.

slide-77
SLIDE 77

77/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo Identify all the methods available on o an IdentitySet(#handles: #longPrintString #actionMap #hasContentsInExplorer [...] #foo: [...] #i: [...] #creationStamp) Invoke a method using its name foo This is foo: 42

slide-78
SLIDE 78

78/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo |o|

  • := C newWithi: 42.

Transcript show: 'Identify all the methods available on o' ; cr. Transcript show: C allSelectors ; cr. Transcript show: 'Invoke a method using its name foo' ; cr. (C compiledMethodAt: #foo:) valueWithReceiver: o arguments: #('This is foo: ').

Simple and straightforward

slide-79
SLIDE 79

79/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time Object subclass: #C instanceVariableNames: 'i' classVariableNames: '' poolDictionaries: '' category: 'CSE3009'. C class compile: 'newWithi: anInt ^(self new) i: anInt ; yourself.'. C compile: 'foo: aText Transcript show: aText. Transcript show: i. Transcript cr.'. C compile: 'i: anInt i := anInt.'.

slide-80
SLIDE 80

80/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time Save on disk the complete state of o 42 Restore from disk the object o at a later time This is foo on o2: 43

slide-81
SLIDE 81

81/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time |o1 o2|

  • 1 := C newWithi: 42.

Transcript show: 'Save on disk the complete state of o' ; cr. Transcript show: (o1 instVarAt: 1) ; cr. Transcript show: 'Restore from disk the object o at a later time' ; cr.

  • 2 := C new.
  • 2 instVarNamed: 'i' put: 43.
  • 2 foo: 'This is foo on o2: '.

Again, simple and straightforward

slide-82
SLIDE 82

82/182

Scenarios

Scenario 2:

– Pharo (a recent implementation of Smalltalk) provides is a general object serialiser that can serialise any object – Uses reflection to implement these methods!

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time 1@2 serializeToFileNamed: 'hello.fuel'. FLMaterializer materializeFromFileNamed: 'hello.fuel'

Thanks to Marcus Denker for pointing out these helper methods

slide-83
SLIDE 83

83/182

Scenarios

Scenario 3:

Object subclass: #C instanceVariableNames: 'i' classVariableNames: 'NumberOfInstances' poolDictionaries: '' category: 'CSE3009'. C class compile: 'newWithi: anInt ^(self new) i: anInt ; yourself.'. C compile: 'foo: aText Transcript show: aText. Transcript show: i. Transcript cr.'. C compile: 'i: anInt i := anInt.'. – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

Only difference with Scenarios 1 and 2

slide-84
SLIDE 84

84/182

Scenarios

Scenario 3:

C class compile: 'newWithi: anInt ^(self new) i: anInt ; yourself.'. C compile: 'foo: aText Transcript show: aText. Transcript show: i. Transcript cr.'. C compile: 'i: anInt i := anInt.'.

Same as Scenarios 1 and 2

– Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-85
SLIDE 85

85/182

Scenarios

Scenario 3:

C class compile: 'initialize NumberOfInstances := 0.'. C class compile: 'new NumberOfInstances := NumberOfInstances + 1. ^ self basicNew initialize.'. C class compile: 'numberOfInstances ^ NumberOfInstances.'. – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

“Write access” to the metaclass

slide-86
SLIDE 86

86/182

Scenarios

Scenario 3:

|o1 o2 o3| C initialize.

  • 1 := C newWithi: 42.
  • 2 := C newWithi: 1.
  • 3 := C newWithi: 100.

Transcript show: o1 ; show: ' ' ; show: o2 ; show: ' ' ; show: o3 ; cr. Transcript show: C numberOfInstances. – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-87
SLIDE 87

87/182

Scenarios

Scenario 3:

a C a C a C 3

To fulfill this scenario, we modified C class not C

– Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-88
SLIDE 88

88/182

Scenarios

Scenario 3:

In Smalltalk, each class has one anonymous meta-class, which can be modified

  • Adding new variables and methods which are thus

class variables and class methods

  • These methods apply on the class, these fields

belong to the class (thus unique)

– Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-89
SLIDE 89

89/182

Scenarios

Scenario 3:

– What about a subclass D of C? – How would its instances be counted?

a C a C a C 3 – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

Thanks to Christophe Dony for suggesting this use of class vs. class instance variables

slide-90
SLIDE 90

90/182

Scenarios

Scenario 3:

– In C++ and Java: static = global

  • The class variables is shared by all the instances of

its declaring class… and its subclasses!

final D o4 = new D(); // Eclipse advises to use C to call getNumberOfInstances(). System.out.println(o4); System.out.println(D.getNumberOfInstances()); – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-91
SLIDE 91

91/182

Scenarios

Scenario 3:

– In Smalltalk: class vs. class instance

  • Class variable vs. class instance variable

– A class variable is shared by all the instance of the class and all the instances of its subclasses – A class instance variable is unique to each class, inherited from the super-class, like instance variables

C class instanceVariableNames: 'IndividualClassNumberOfInstances' – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-92
SLIDE 92

92/182

Scenarios

Scenario 3:

– In Smalltalk: class vs. class instance

C subclass: #D instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ptidej'. D class compile: 'initialize IndividualClassNumberOfInstances := 0.'. D class compile: 'new NumberOfInstances := NumberOfInstances + 1. IndividualClassNumberOfInstances := IndividualClassNumberOfInstances + 1. ^ self basicNew initialize.'. D class compile: 'numberOfInstances ^ NumberOfInstances.'. D class compile: 'individualClassNumberOfInstances ^ IndividualClassNumberOfInstances.'. – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-93
SLIDE 93

93/182

Scenarios

Scenario 3:

– In Smalltalk: class vs. class instance

| o4 | D initialize.

  • 4 := D new.

Transcript show: o4 ; cr. Transcript show: C numberOfInstances ; cr. Transcript show: D numberOfInstances ; cr. Transcript show: D individualClassNumberOfInstances ; cr. – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends a D 4 4 1

slide-94
SLIDE 94

94/182

Scenarios

Scenario 3:

– In Java: the JVM contains the world

  • Possible to connect to a JVM using the Java Debug

Interface of the Java Platform Debug Architecture

  • Possible to reify the classes existing in the remote

JVM and to obtain their instances

com.sun.jdi.ReferenceType.instances(long)

  • Special feature of the JVM, “outside” of the normal

constructs of the language

– Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

http://stackoverflow.com/questions/1947122/ is-there-a-simple-way-of-obtaining-all-object-instances-of-a-specific-class-in-j/1947200#1947200

slide-95
SLIDE 95

95/182

Scenarios

Scenario 3:

– In Smalltalk: the image contains the world

  • Possible to ask it all the instances of a particular class
  • r all the instances currently in memory

Transcript show: (C allInstances size). – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

Thanks to Marcus Denker for pointing out this solution

slide-96
SLIDE 96

96/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() Object subclass: #C instanceVariableNames: 'i' classVariableNames: '' poolDictionaries: '' category: 'CSE3009'. C class compile: 'newWithi: anInt ^(self new) i: anInt ; yourself.'. C compile: 'foo: aText Transcript show: aText. Transcript show: i. Transcript cr.'. C compile: 'i: anInt i := anInt.'.

slide-97
SLIDE 97

97/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() This is o: 42 Intercepting message send: foo: Original arguments: This is o: New arguments: THIS IS O: THIS IS O: 42

slide-98
SLIDE 98

98/182

Scenarios

Scenario 4:

Several choices

  • ObjectWrappers: http://magaloma.seasidehosting.st/

Kernel#ObjectTracer

  • MethodWrappers: http://pharo.gforge.inria.fr/

PBE1/PBE1ch15.html

  • Reflectivity: http://scg.unibe.ch/Research/Reflectivity

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-99
SLIDE 99

99/182

Scenarios

Scenario 4:

Several choices

  • ObjectWrappers: http://magaloma.seasidehosting.st/

Kernel#ObjectTracer

  • MethodWrappers: http://pharo.gforge.inria.fr/

PBE1/PBE1ch15.html

  • Reflectivity: http://scg.unibe.ch/Research/Reflectivity

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-100
SLIDE 100

100/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() | o aWrapper |

  • := C newWithi: 42.
  • foo: 'This is o: '.

aWrapper := WrapperForC on: o. "o become: aWrapper." aWrapper foo: 'This is o: '. aWrapper xxxUnTrace.

slide-101
SLIDE 101

101/182

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() ObjectTracer subclass: #WrapperForC instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'CSE3009'. WrapperForC compile: 'doesNotUnderstand: aMessage "Intercept the selector foo:" | sel arg newArg | sel := aMessage selector. sel = ''foo:'' ifTrue: [ arg := (aMessage arguments) at: 1. newArg := arg asUppercase. Transcript show: ''Intercepting message send: '' ; show: sel ; cr. Transcript tab ; show: ''Original arguments: '' ; show: arg ; cr. Transcript tab ; show: ''New arguments: '' ; show: newArg ; cr. aMessage argument: newArg. aMessage sendTo: (self xxxViewedObject) ] ifFalse: [ "Transcript show: aMessage." ]'.

slide-102
SLIDE 102

102/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() This is o: 42 Intercepting message send: foo: Original arguments: This is o: New arguments: THIS IS O: THIS IS O: 42 | o aWrapper |

  • := C newWithi: 42.
  • foo: 'This is o: '.

aWrapper := WrapperForC on: o. "o become: aWrapper." aWrapper foo: 'This is o: '. aWrapper xxxUnTrace.

slide-103
SLIDE 103

103/182

Scenarios

Scenario 4:

– We created the class WrappedForC that does not understand many messages (as subclass

  • f ProtoObject)

– We wrapped an instance of WrappedForC around o and use doesNotUnderstand: to proxy messages

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-104
SLIDE 104

104/182

Scenarios

Scenario 4:

– We created the class WrappedForC that does not understand many messages (as subclass

  • f ProtoObject)

– We wrapped an instance of WrappedForC around o and use doesNotUnderstand: to proxy messages

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-105
SLIDE 105

105/182

Scenarios

Scenario 4:

Several choices

  • ObjectWrappers: http://magaloma.seasidehosting.st/

Kernel#ObjectTracer

  • MethodWrappers: http://pharo.gforge.inria.fr/

PBE1/PBE1ch15.html

  • Reflectivity: http://scg.unibe.ch/Research/Reflectivity

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-106
SLIDE 106

106/182

Scenarios

Reflectivity

– Marcus Denker, RMOD Team, INRIA Lille, and others – Extensions to the standard reflection features of Smalltalk (both structural and behavioural)

  • Structural reflection is extended by sub-method

reflection: method bodies are first-class

  • Behavioural reflection is provided by Geppetto, an

implementation of Partial Behavioural Reflection

slide-107
SLIDE 107

107/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() Object subclass: #C instanceVariableNames: 'i' classVariableNames: '' poolDictionaries: '' category: 'CSE3009'. C class compile: 'newWithi: anInt ^(self new) i: anInt ; yourself.'. C compile: 'foo: aText Transcript show: aText. Transcript show: i. Transcript cr.'. C compile: 'i: anInt i := anInt.'.

slide-108
SLIDE 108

108/182

Scenarios

Scenario 4:

– Sub-method reflection

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() nodes := (C>>#foo:) sends select: [:each | ((each selector ~= #show:)

  • r: (each arguments) size ~= 1)

ifTrue: [ false ] ifFalse: [ (each arguments at: 1) name = 'aText'. ]. ].

slide-109
SLIDE 109

109/182

Scenarios

Scenario 4:

– Meta-object

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() gpLink := GPLink metaObject: [:arg1 :node | | newArg | newArg := arg1 asUppercase. Transcript show: 'Intercepting message send: '. Transcript show: node ; cr. Transcript tab ; show: 'Original arguments: '. Transcript show: arg1 ; cr. Transcript tab ; show: 'New arguments: '. Transcript show: newArg ; cr. Transcript show: newArg. ]. gpLink control: #instead.

slide-110
SLIDE 110

110/182

Scenarios

Scenario 4:

– Linking

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

  • := C newWithi: 42.
  • foo: 'This is o: '.

nodes do: [:node | node link: gpLink].

  • foo: 'This is o: '.

gpLink uninstall. This is o: 42 Intercepting message send: foo: Original arguments: This is o: New arguments: THIS IS O: THIS IS O: 42

slide-111
SLIDE 111

111/182

Scenarios

Scenarios 1, 2, 3, and 4

More difficult to implement “as is”

  • http://stackoverflow.com/questions/359237/why-does-

c-not-have-reflection

  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/

2005/n1751.html

slide-112
SLIDE 112

112/182

Scenarios

Scenarios 1, 2, 3, and 4

Third-party solutions

  • Mirror: http://kifri.fri.uniza.sk/~chochlik/mirror-

lib/html/index.html#introduction

  • VisualStudio.NET: http://msdn.microsoft.com/en-

us/library/y0114hz2%28v=vs.110%29.aspx

slide-113
SLIDE 113

113/182

Scenarios

Scenarios 1, 2, 3, and 4

Third-party solutions

  • Mirror: http://kifri.fri.uniza.sk/~chochlik/mirror-

lib/html/index.html#introduction

  • VisualStudio.NET: http://msdn.microsoft.com/en-

us/library/y0114hz2%28v=vs.110%29.aspx

slide-114
SLIDE 114

114/182

Scenarios

Mirror

– Matúš Chochlík, University of Žilina, Žilina, Slovakia “[C]ompile-time and run-time meta-data describing C++ constructs like namespaces, types typedef-ined types, enums, classes with their base classes, member variables, constructors, member functions, etc.”

slide-115
SLIDE 115

115/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo namespace cse3009 { class C { private: int i; public: C(const int _i) : i(_i) { } int get_i(void) const { return this->i; } void set_i(const int _i) { this->i = _i; } void foo(const std::string _s) const { std::cout << _s << this->i << std::endl; } }; }

slide-116
SLIDE 116

116/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo Identify all the methods available on o (The type of o is cse3009::C) cse3009::C::i cse3009::C::foo Invoke a method using its name foo This is foo: 42

slide-117
SLIDE 117

117/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo int main(void) { cse3009::C * o = new cse3009::C(42); std::cout << "Identify all the methods available on o" << std::endl; identify_members(o); std::cout << "Invoke a method using its name foo" << std::endl; invoke_member_function(o); return 0; }

slide-118
SLIDE 118

118/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo template<typename O> void identify_members(O * _o) { using namespace mirror; typedef MIRRORED_CLASS(O) meta_Class; std::cout << "\t(The type of o is " << meta_Class::full_name() << ")" << std::endl; std::cout << "\t"; mp::for_each_ii< all_member_variables<meta_Class> >(info_printer()); std::cout << std::endl << "\t"; mp::for_each_ii< member_functions<meta_Class> >(info_printer()); std::cout << std::endl; }

slide-119
SLIDE 119

119/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo template<typename O> void invoke_member_function(O * _o) { using namespace mirror; typedef MIRRORED_CLASS(cse3009::C) meta_Class; typedef mp::at_c<overloads< mp::at_c<member_functions<meta_Class>, 0>::type>, 0>::type meta_foo; my_invoker_maker::invoker<meta_foo>::type invoker( std::string("\tThis is foo: ")); invoker.call_on(*_o); }

slide-120
SLIDE 120

120/182

Scenarios

Mirror

– Provides essentially the same concepts and features as java.lang.reflect of Java – Uses templates and (manual) registration to collect metadata that does not exist unless manually created through macro preprocessing

slide-121
SLIDE 121

121/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo MIRROR_REG_BEGIN MIRROR_QREG_GLOBAL_SCOPE_NAMESPACE(std) MIRROR_REG_CLASS_BEGIN(struct, std, string) MIRROR_REG_CLASS_END MIRROR_QREG_GLOBAL_SCOPE_NAMESPACE(cse3009) MIRROR_REG_CLASS_BEGIN(class, cse3009, C) MIRROR_REG_CLASS_MEM_VARS_BEGIN MIRROR_REG_CLASS_MEM_VAR_GET_SET( private, _, int, i, _.get_i(), _.set_i(_i)) MIRROR_REG_CLASS_MEM_VARS_END MIRROR_REG_MEM_FUNCTIONS_BEGIN MIRROR_REG_MEM_OVLD_FUNC_BEGIN(foo) MIRROR_REG_MEM_FUNCTION_BEGIN(public, _, void, foo, 1) MIRROR_REG_MEM_FUNCTION_PARAM(std::string, _s) MIRROR_REG_MEM_FUNCTION_END(1, _) MIRROR_REG_MEM_OVLD_FUNC_END(foo) MIRROR_REG_MEM_FUNCTIONS_END MIRROR_REG_CLASS_END MIRROR_REG_END

slide-122
SLIDE 122

122/182

Scenarios

Scenario 1:

– Given a class C – Given an object o, instance of C – Identify all the methods available on o – Invoke a method using its name foo template<class Unused> struct my_manufacturer<std::string, Unused> { const std::string s; template<class ConstructionInfo> inline my_manufacturer(const std::string _s, const ConstructionInfo construction_info) : s(_s) { } void finish(std::string) const { } inline std::string operator()(void) const { return s; } }; typedef mirror::invoker_maker<my_manufacturer, mirror::default_fact_suppliers, my_enumerator, void> my_invoker_maker;

slide-123
SLIDE 123

123/182

Scenarios

Mirror

– Uses complex code that can be easily and advantageously hidden in libraries – Will possibly become part of Boost and the standard reflection library for C++

  • http://kifri.fri.uniza.sk/~chochlik/jtc1_sc22_wg21/

std_cpp_refl-latest.pdf

slide-124
SLIDE 124

124/182

Scenarios

Scenario 2:

namespace cse3009 { class C { private: int i; public: C(const int _i) : i(_i) { } int get_i(void) const { return this->i; } void set_i(const int _i) { this->i = _i; } void foo(const std::string _s) const { std::cout << _s << this->i << std::endl; } }; } – Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time

slide-125
SLIDE 125

125/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time Save on disk the complete state of o (The type of o is cse3009::C) cse3009::C::i = 42 Restore from disk the object o at a later time 43

slide-126
SLIDE 126

126/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time int main(void) { cse3009::C * o = new cse3009::C(42); std::cout << "Save on disk the complete state of o" << std::endl; save_on_disk(o); std::cout << "Restore from disk the object o at a later time" << std::endl; restore_from_disk<cse3009::C>(); return 0; }

slide-127
SLIDE 127

127/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time template<typename O> void save_on_disk(O * _o) { using namespace mirror; typedef MIRRORED_CLASS(O)meta_Class; std::cout << "\t(The type of o is " << meta_Class::full_name() << ")" << std::endl << "\t"; mp::for_each_ii<all_member_variables<meta_Class>>( info_printer_variables<O>(*_o)); std::cout << std::endl; }

slide-128
SLIDE 128

128/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time template<class O> struct info_printer_variables { O o; inline info_printer_variables(O _o) : o(_o) { } template<class IterInfo> void operator()(IterInfo) { using namespace mirror; std::cout << IterInfo::type::full_name() << " = " << IterInfo::type::get(o); if (!IterInfo::is_last::value) std::cout << ", "; } };

Get the value of reflected variable

slide-129
SLIDE 129

129/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time template<typename O> void restore_from_disk(void) { using namespace mirror; typedef typename my_factory_maker::factory<O>::type my_factory_type; my_factory_type my_factory(43); O o(my_factory()); std::cout << "\t" << o.get_i() << std::endl; }

slide-130
SLIDE 130

130/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time typedef mirror::factory_maker< my_manufacturer, mirror::default_fact_suppliers, my_enumerator, void> my_factory_maker;

Factory generating instances

  • f (possibly) different types
slide-131
SLIDE 131

131/182

Scenarios

Scenario 2:

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time template<class Unused> struct my_manufacturer<void, Unused> { template<typename Context> my_manufacturer(int _value, Context) { } void finish(int) { } template<class ConstructionInfo> inline int add_constructor( int _value, ConstructionInfo) const { return _value; } inline int index(void) { return 0; } };

To pass on to the constructor

slide-132
SLIDE 132

132/182

template<class Product, typename IsEnum> struct my_base_manufacturer { Product x; struct constr_param_name_printer { template<class IterInfo> inline void operator()(IterInfo) const { if (!IterInfo::is_first::value) std::cout << ", "; std::cout << IterInfo::type::base_name(); } }; struct constr_context_printer { template<class IterInfo> inline void operator()(IterInfo) const { if (!IterInfo::is_first::value) std::cout << "::"; std::cout << IterInfo::type::base_name(); } }; template<class ConstructionInfo> my_base_manufacturer(int tabs, ConstructionInfo construction_info, const Product& _x) : x(tabs) { } void finish(int) { } inline Product operator()(void) { return x; } }; template<class Product, class Unused> struct my_enumerator : my_base_manufacturer<Product, std::true_type> { template<class ConstructionInfo> inline my_enumerator(int tabs, ConstructionInfo construction_info) : my_base_manufacturer<Product, std::true_type>( tabs, construction_info, Product()) { } void finish(int) { } inline Product operator()(void) { return NULL; } }; template<class Product, class Unused> struct my_manufacturer { typedef typename mirror::factory_maker< my_manufacturer, mirror::default_fact_suppliers, my_enumerator, Unused> maker; typename maker::template factory<Product>::type f; template<class ConstructionInfo> inline my_manufacturer( int _value, ConstructionInfo construction_info) : f(construction_info) { } void finish(int) { } inline Product operator()(void) { return f(); } };

Less complex than it looks! Can be replaced by existing factories

slide-133
SLIDE 133

133/182

Scenarios

Scenario 2:

– Mirror provides many ready-to-use factories

  • From strings (mirror/example/factories/tetrahedron_script.cpp)
  • From a SOCI database (mirror/example/factories/tetrahedron_soci.cpp)

– Given an object o, instance of C – Save on disk the complete state of o – Restore from disk the object o at a later time // make the input object for the factory script_factory_input in; // create a factory plugged with the script parser script_factory_maker::factory<tetrahedron>::type f = in.data(); // make a tetrahedron object factory soci_quick_factory_maker::factory<test::tetrahedron>::type tetrahedron_factory = soci_fact_data(r); while(r != e) { test::tetrahedron t = tetrahedron_factory(); // and write it to std output std::cout << stream::to_json::from(t, [&i](std::ostream& out) {

  • ut << "tetrahedron_" << i; } ) << std::endl;
slide-134
SLIDE 134

134/182

Scenarios

Scenario 3:

namespace cse3009 { class C { private: int i; static int numberOfInstances; public: C(const int _i) : i(_i) { numberOfInstances++; } ... void foo(const std::string _s) const { std::cout << _s << this->i << std::endl; } static int getNumberOfInstances() { return numberOfInstances; } }; } – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-135
SLIDE 135

135/182

Scenarios

Scenario 3:

int cse3009::C::numberOfInstances = 0; int main(void) { cse3009::C * o1 = new cse3009::C(42); cse3009::C * o2 = new cse3009::C(1); cse3009::C * o3 = new cse3009::C(100); std::cout << o1 << std::endl << o2 << std::endl << o3 << std::endl; std::cout << cse3009::C::getNumberOfInstances() << std::endl; return 0; } – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

slide-136
SLIDE 136

136/182

Scenarios

Scenario 3:

0x800418f8 0x80041908 0x80041918 3 – Given a class C – Record the numbers of its instance ever created – Report this number when the program ends

To fulfill this scenario, we must modify C as in Java

slide-137
SLIDE 137

137/182

Scenarios

Scenario 4:

– Several choices

  • Bjarne Stroustrup's Template:

http://www.stroustrup.com/wrapper.pdf

  • Herb Sutter's Functor-based Approach:

http://channel9.msdn.com/Shows/Going+Deep/ C-and-Beyond-2012-Herb-Sutter-Concurrency-and- Parallelism

  • Ion Armagedescu’s CPatcher:

http://www.codeproject.com/Articles/34237/A-C-Style-

  • f-Intercepting-Functions

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-138
SLIDE 138

138/182

Scenarios

Scenario 4:

– Several choices

  • Bjarne Stroustrup's Template:

http://www.stroustrup.com/wrapper.pdf

  • Herb Sutter's Functor-based Approach:

http://channel9.msdn.com/Shows/Going+Deep/ C-and-Beyond-2012-Herb-Sutter-Concurrency-and- Parallelism

  • Ion Armagedescu’s CPatcher:

http://www.codeproject.com/Articles/34237/A-C-Style-

  • f-Intercepting-Functions

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-139
SLIDE 139

139/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() Bjarne Stroustrup's Template: (Prefix::operator->()) This is o: 42

slide-140
SLIDE 140

140/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() int main(void) { std::cout << "Bjarne Stroustrup's Template:" << std::endl; cse3009::C o2(42); Prefix<cse3009::C> prefixed_o2(&o2); prefixed_o2->foo("This is o: "); std::cout << std::endl; return 0; }

slide-141
SLIDE 141

141/182

Scenarios

Scenario 4:

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() template<class T> class Prefix { T* p; public: Prefix(T * _p) : p(_p) { } T* operator->() { std::cout << "(Prefix::operator->())" << std::endl; return p; } };

slide-142
SLIDE 142

142/182

Scenarios

Scenario 4:

– Is similar to a proxy in Java – Cannot easily access and modify the arguments of the proxy’ed method call – Makes it difficult to do something after the

  • riginal method call

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-143
SLIDE 143

143/182

Scenarios

Scenario 4:

– Several choices

  • Bjarne Stroustrup's Template:

http://www.stroustrup.com/wrapper.pdf

  • Herb Sutter's Functor-based Approach:

http://channel9.msdn.com/Shows/Going+Deep/ C-and-Beyond-2012-Herb-Sutter-Concurrency-and- Parallelism

  • Ion Armagedescu’s CPatcher:

http://www.codeproject.com/Articles/34237/A-C-Style-

  • f-Intercepting-Functions

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-144
SLIDE 144

144/182

Scenarios

Scenario 4:

Dependent on the compiler! GCC v4.8.2 vs. Microsoft Visual Studio Express 2013

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() Visual C++ 2013 06157-004-0441005-02428

slide-145
SLIDE 145

145/182

Scenarios

Scenario 4:

– GCC v4.8.2

In file included from ..\Source\scenario4.cpp:32:0: ..\Source\../CPatcher/patcher.h: In instantiation of 'void CPatch::HookClassFunctions(T1&, T2, bool, bool) [with T1 = void (cse3009::C::*)(std::basic_string<char>); T2 = void (class_for_patches::*)(std::basic_string<char>)]': ..\Source\../CPatcher/patcher_defines.h:131:2: required from 'CPatch::CPatch(TReturnVal (TClassSource::*&)(TArg1), TReturnVal (TClassTarget::*)(TArg1), bool, bool) [with TClassSource = cse3009::C; TClassTarget = class_for_patches; TReturnVal = void; TArg1 = std::basic_string<char>]' ..\Source\scenario4.cpp:52:61: required from here

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-146
SLIDE 146

146/182

Scenarios

Scenario 4:

– GCC v4.8.2 may not be legal

  • http://www.codeproject.com/Articles/34237/A-C-Style-
  • f-Intercepting-Functions?msg=4796042
  • http://stackoverflow.com/questions/1307278/casting-

between-void-and-a-pointer-to-member-function

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() *reinterpret_cast<long*>(&fn_funcToHook) *reinterpret_cast<long*>(&fn_Hook)

slide-147
SLIDE 147

147/182

Scenarios

Scenario 4:

– Microsoft Visual Studio Express 2013

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() void(ptidej::C::*pfn_foo)(const std::string) = &ptidej::C::foo; class proxy { public: void my_foo(const std::string s) { std::cout << "Function foo() is patched!" << std::endl << std::flush; (reinterpret_cast<ptidej::C*>(this)->*pfn_foo)(s); } }; int _tmain(int argc, _TCHAR* argv[]) { CPatch patch_aclass_doSomething(pfn_foo, &proxy::my_foo); ptidej::C o(42);

  • .foo(std::string("This is o: "));

return 0; }

slide-148
SLIDE 148

148/182

Scenarios

Scenario 4:

– Microsoft Visual Studio Express 2013

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo() Function foo() is patched! This is o: 42

slide-149
SLIDE 149

149/182

Scenarios

Scenario 4:

– Is similar to a proxy in Java – Can easily access and modify the arguments

  • f the proxy’ed method call

– Makes it difficult to do something after the

  • riginal method call

– Given an object o, instance of C – Without changing o or C – Change the behaviour of o.foo()

slide-150
SLIDE 150

150/182

Scenarios

Java

  • Smalltalk
  • C++
slide-151
SLIDE 151

151/182

Conclusion

Java

  • Smalltalk
  • C++
  • Differences in semantics

and syntax mostly due to the presence (or absence)

  • f virtual machines
slide-152
SLIDE 152

152/182

Conclusion

Scenario 1: invoke an arbitrary method on an object (see

the problems with instanceof and plugins)

Scenario 2: access the complete (including private) state of

an object (see the problem with serialisation)

Scenario 3: count the number of instances of a class

created at runtime (see the problem with debugging/profiling)

Scenario 4: modify the behaviour at run-time of a method

without the need to recompile and restart the program (see the problem with patching)

slide-153
SLIDE 153

153/182

Conclusion

Reflection helps addressing these scenarios

– Depends on the capabilities of the programming language and underlying execution environment – Yields more or less elegant code

Use reflection sparingly and purposefully

– Complexity – Performance

slide-154
SLIDE 154

154/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-155
SLIDE 155

155/182

Theory

Class

– A programming construct that encapsulates some state (fields) and behaviours (methods) – A construct whose instances are objects

Metaclass

– A programming construct that encapsulates some state (fields) and behaviours (methods) – A construct whose instances are classes

Aristote (Ἀριστοτέλης) *-384 †-322

slide-156
SLIDE 156

156/182

Theory

An object is an instance of a class

– A class generates an object

A class is an instance of a metaclass

– A metaclass generates a class

A metaclass is an instance of…

(a) A meta-metaclass? (b) Itself?

slide-157
SLIDE 157

157/182

Theory

An object is an instance of a class

– A class generates an object

A class is an instance of a metaclass

– A metaclass generates a class

A metaclass is an instance of…

(a) A meta-metaclass? (b) Itself

slide-158
SLIDE 158

158/182

Theory

The class Object is the parent of all

classes, including metaclasses

The class Class is the generator of all

classes, including Object

slide-159
SLIDE 159

159/182

Des langages de programmation à objets à la représentation des connaissances à travers le MOP : vers une intégration par Gabriel Pavillet. Thèse de doctorat en Informatique sous la direction de Roland Ducournau, soutenue en 2000 à Montpellier 2

slide-160
SLIDE 160

160/182

Theory

The classes

– Class – Method – Field – …

reify constructs of the programming languages, they become first-class entities, to allow programs to manipulate these constructs at runtime

slide-161
SLIDE 161

161/182

Theory

Java

Field

∈ C

Method ∈ C Static field ∈ C Static method ∈ C

  • Smalltalk

Instance variable

∈ C

Instance method

∈ C

Class variable

∈ C class

Class method

∈ C class

Class instance variables

– To count the numbers of instances of subclasses of C (D, E…) independently from

  • ne another
slide-162
SLIDE 162

162/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-163
SLIDE 163

163/182

Theory

Earlier, we said that reflection is of

– Theoretical interest

  • What is an interpreter?

Brian Cantwell Smith “Procedural Reflection in Programming Languages” (Ph.D. thesis, 1982)

– Practical interest

  • Libraries
  • Frameworks
slide-164
SLIDE 164

164/182

Theory

Earlier, we said that reflection is of

– Theoretical interest

  • What is an interpreter?

Brian Cantwell Smith “Procedural Reflection in Programming Languages” (Ph.D. thesis, 1982)

– Practical interest

  • Libraries
  • Frameworks
slide-165
SLIDE 165

165/182

Theory

Earlier, we said that reflection is of

– Theoretical interest

  • What is an interpreter?

Brian Cantwell Smith “Procedural Reflection in Programming Languages” (Ph.D. thesis, 1982)

– Practical interest

  • Libraries
  • Frameworks

A virtual machine is an interpreter

slide-166
SLIDE 166

166/182

Theory

In Java, the metaclass is anonymous and

cannot be modified

In Smalltalk, “[t]here is only one instance of a

particular Metaclass, namely the class which is being described”

slide-167
SLIDE 167

167/182

Theory

Many other variations are possible

– LISP

  • http://www.cliki.net/mop

– Perl 5, 6

  • http://search.cpan.org/perldoc?Class::MOP

– Python

  • https://www.python.org/doc/essays/metaclasses/

– MetaclassTalk – Noury Bouraqadi, Pierre Cointe

  • http://csl.ensm-douai.fr/MetaclassTalk

– NeoClassTalk – Fred Rivard, Pierre Cointe

  • http://c2.com/cgi/wiki?NeoClassTalk

– OpenC++ – Shigeru Chiba, Gregor Kiczales

  • http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/openc++.html
slide-168
SLIDE 168

168/182

Theory

A Meta Object Protocol exposes some or all

internal structure of the interpreter to the programmer

The MOP is (often) a set of classes and

methods that allow a program to inspect the state of the supporting system and alter its behaviour

slide-169
SLIDE 169

169/182

Theory

MOP can be accessible at

– Compile-time

  • OpenJava

– http://www.csg.ci.i.u-tokyo.ac.jp/openjava/

– Load-time

  • Javassist

– http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/

– Run-time

  • AspectJ

– http://eclipse.org/aspectj/

slide-170
SLIDE 170

170/182

Bibliothèques et le chargement de composantes dynamiques

1.

Introduction

2.

Bibliothèques et cadriciels

– Types d’interconnexions – Problèmes légaux – Chargement dynamique

3.

Réflexion

4.

Théorie

– Méta-classes – Protocoles de méta-objets (MOP) – MOP à la compilation, à l’exécution

5.

Retour sur le chargement dynamique

slide-171
SLIDE 171

171/182

Class Loading

Virtual machines

– Interpreters – Closed world

Must

– Access resources – Load classes

slide-172
SLIDE 172

172/182

Class Loading

Virtual machines

– Interpreters – Closed world

Must

– Access resources – Load classes

slide-173
SLIDE 173

173/182

Class Loading

Virtual machines

– Interpreters – Closed world

Must

– Access resources – Load classes

slide-174
SLIDE 174

174/182

Class Loading

Example

– Given an interface ICommand – Load at runtime a class implementing ICommand using its binary name

  • A binary name is in the form

<pckg1>.….<pckgn>.<ClassName>

– net.ptidej.reflection.java.scenario1.C

final Class<ICommand> command = this.classLoader.loadClass(binaryName);

slide-175
SLIDE 175

175/182

Class Loading

http://map.sdsu.edu/geog583/images/week8.3.gif

slide-176
SLIDE 176

176/182

Class Loading

http://www.onjava.com/2005/01/26/graphics/Figure01_MultipleClassLoaders.JPG

slide-177
SLIDE 177

177/182

Class Loading

public class ClassLoader extends java.lang.ClassLoader { private final String directory; public ClassLoader( final java.lang.ClassLoader parent, final String directory) { super(parent); this.directory = directory; }

slide-178
SLIDE 178

178/182

Class Loading

protected Class findClass(final String name) { Class newClass = null; try { newClass = super.findClass(name); } catch (final ClassNotFoundException cnfe) { final String osName = this.directory + name.replace('.', '/') + ".class"; try { final FileInputStream fis = new FileInputStream(osName); newClass = this.defineClasses(name, fis); } catch (final ClassFormatError cfe) { cfe.printStackTrace(Output.getInstance().errorOutput()); } catch (final FileNotFoundException fnfe) { // fnfe.printStackTrace(); } } return newClass; }

Use the method defined in the superclass on this CL

slide-179
SLIDE 179

179/182

Class Loading

private Class defineClasses(final String name, final InputStream inputStream) { try { int b; int length = 0; byte[] bytes = new byte[4]; while ((b = inputStream.read()) != -1) { if (length == bytes.length) { final byte[] temp = new byte[length + 4]; System.arraycopy(bytes, 0, temp, 0, length); bytes = temp; } bytes[length] = (byte) b; length++; } System.out.println(name); final Class newClass = this.defineClass(name, bytes, 0, length); return newClass; } catch (final IOException ioe) { return null; } catch (final NoClassDefFoundError ncdfe) { ncdfe.printStackTrace(Output.getInstance().errorOutput()); return null; } }

Use the method defined in the superclass on this CL

slide-180
SLIDE 180

180/182

Class Loading

http://www.onjava.com/2005/01/26/graphics/Figure01_MultipleClassLoaders.JPG

slide-181
SLIDE 181

181/182

Class Loading

protected Class findClass(final String name) { Class newClass = null; try { newClass = this.getParent().loadClass(name); } catch (final ClassNotFoundException cnfe) { final String osName = this.directory + name.replace('.', '/') + ".class"; try { final FileInputStream fis = new FileInputStream(osName); newClass = this.defineClasses(name, fis); } catch (final ClassFormatError cfe) { cfe.printStackTrace(Output.getInstance().errorOutput()); } catch (final FileNotFoundException fnfe) { // fnfe.printStackTrace(); } } return newClass; }

Ask the parent CL if it already knows the class

slide-182
SLIDE 182

182/182

Conclusion

Virtual machines must access resources and

load classes, in specific cases

– Can extend ClassLoader – Must override (typically) method

  • Class findClass(String)

– Must be careful with inheritance vs. delegation!

  • super vs. getParent()