Affichage des articles dont le libellé est Java. Afficher tous les articles
Affichage des articles dont le libellé est Java. Afficher tous les articles

mardi 24 mai 2016

Externaliser la configuration d'une webapp


Comment permettre à une application web Java de récupérer un paramètre de configuration sans avoir à repackager le ".war" ?



Si on s'interdit de modifier le fichier ".war" ça veut dire que l'on ne peut plus utiliser les possibilités de configuration à partir des fichiers qu'il contient ( web.xml, fichiers properties, etc ).
Les paramètres de configuration devront donc être portés par les environnements d'exécution de l'application (et non par l'application elle même), c'est à dire le server d'applications ( Tomcat, Jetty, etc ) ou le système d'exploitation.
Les trois possibilités les plus courantes sont décrites ci-après...

1) Utiliser une variable d'environnement

- Définir la variable d'environnement au niveau du système d'exploitation
Exemple sous Linux  :
   export MYFOLDER=/tmp/foo

- Récupérer la valeur de cette variable dans le code Java,
  par exemple dans une classe de type  "ServletContextListener" :
    String value = System.getenv("MYFOLDER")

Cette solution est simple et applicable indépendamment type de serveur d'applications.
Mais elle nécessite une intervention au niveau "système d'exploitation" (pas toujours possible) et on ne peut avoir qu'une seule valeur pour toutes les instances de serveurs d'application sur un même OS.


2) Configurer une propriété de type "Java System property"

Il s'agit de définir une propriété pour la JVM au lancement du serveur d'applications.

- Définir la propriété pour un serveur d'applications particulier :
Soit avec l'option "-D" de la ligne de commande
Soit en utilisant les fichiers de configuration propres à chaque serveur d'application
Exemple pour Tomcat :
        Dans le fichier "catalina.properties" de Tomcat :
    myfolder=/tmp/foo
       
        NB : pour un lancement dans Eclipse utiliser le fichier "catalina.properties"
                 situé dans le workspace (dans  "Servers" )

- Récupérer la valeur de cette propriété dans le code Java :
    String value = System.getProperty("myfolder");


3) Configurer une "valeur nommée" accessible via JNDI

Une "ressource nommée" peut être définie au niveau du serveur d'applications, elle sera ensuite récupérée via JNDI.

- Définir la "ressource nommée" pour le serveur d'applications concerné

Pour Tomcat :
        Dans le fichier "web.xml" de Tomcat (fichier global pour toutes les webapps) :
      <env-entry>
          <env-entry-name>myTextValue</env-entry-name>
          <env-entry-type>java.lang.String</env-entry-type>
          <env-entry-value>foo</env-entry-value>
      </env-entry>
      <env-entry>
          <env-entry-name>myMaxValue</env-entry-name>
          <env-entry-type>java.lang.Integer</env-entry-type>
          <env-entry-value>10</env-entry-value>
      </env-entry>
        NB :
        - respecter l'ordre des tags "name/type/value"
        - pour un lancement dans Eclipse utiliser le fichier "web.xml" situé
          dans le workspace (dans  "Servers" )
       
        cf https://tomcat.apache.org/tomcat-7.0-doc/config/globalresources.html#Environment_Entries 

Pour Jetty :
        Dans le fichier "jetty.xml" ajouter une ressource avec une entrée du type :
     <New class="org.eclipse.jetty.plus.jndi.EnvEntry">
       <Arg></Arg> <!-- scope : empty = JVM scope-->
       <Arg>myTextValue</Arg> <!-- name -->
       <Arg type="java.lang.String">foo</Arg> <!-- value-->
       <Arg type="boolean">true</Arg>  
     </New>

        cf http://www.eclipse.org/jetty/documentation/current/using-jetty-jndi.html

- Récupérer la valeur de cette variable dans le code Java
  Exemple pour une chaine de caractères :

   String name = "myTextValue" ;
   try {
      Object value = InitialContext.doLookup("java:comp/env/"+name);
      System.out.println("JNDI OBJECT '"+ name + "' = '" + value + "'");
   } catch (NamingException e) {
      System.out.println("JNDI OBJECT ERROR : " + e.getMessage());
      e.printStackTrace();
   }


mercredi 28 octobre 2015

JUnit Vade-mecum

Un petit mémo JUnit ...



Cycle de vie des instances et ordre d'exécution :


Remarques : l'API JUnit ne définit aucun ordre d'exécution des tests, ils doivent donc être exécutable dans n'importe quel ordre. Chaque test doit être indépendant des autres.
Cependant JUnit ver 4.11 permet de fixer l'ordre d'exécution avec l'annotation "@FixMethodOrder" qui peut être utilisée au niveau de la classe.
Exemple :
   @FixMethodOrder(MethodSorters.NAME_ASCENDING)
   public class MyTestCase {
      ...
   }

Sous Eclipse, pour faciliter l'utilisation des "assert" avec import statique :
Window / Preferences : Java / Editor / Content Assist / Favorites
ajouter org.junit.Assert.*

lundi 26 août 2013

Eclipse Kepler - Créer un projet web-maven avec WTP et M2E

Après quelques années de galère à essayer de faire cohabiter les plugins WTP, M2E et Maven for WTP, les utilisateurs d'Eclipse commençaient à s'impatienter (surtout en voyant d'autres IDE dans lesquels tout ça était plutôt naturel et simple). Mais cette fois on y est, enfin presque (ouf !)


Il aura fallu attendre Eclipse 4.3 ( "Eclipse Kepler" : http://www.eclipse.org/kepler/ ) pour que la distribution "Eclipse IDE for Java EE Developers" soit livrée avec les plugins Maven pré-installés.

Kepler (qui pèse un peu plus de 250 Mb) arrive avec :
  - Maven Integration for Eclipse ( "m2e" )   ver 1.4.0
  - Maven Integration for Eclipse WTP    ver 1.0.0
Ces même versions sont disponibles pour Eclipse Juno (mais à ajouter manuellement)

Voici donc comment créer un projet web avec Maven et WTP ...

1) Création du projet 


Il s'agit dans un premier temps de créer directement un projet Maven (et non WTP)
en utilisant l' archetype  "maven-archetype-webapp"

File  /  New (ou Alt-Shift-N)  /  Maven project

Sélection de l'archetype pour "web app" :



Après création, le nouveau projet apparait dans le workspace.
Le nom du projet est l' Artefact Id de Maven
Pour changer le nom il suffit de faire  " Refactor / Rename "

2) Structure du projet 


La structure du projet est maintenant presque prête.


Mais parfois il manque des répertoires standards de Maven qui n’ont pas été créés (ça semble se produire à partir du deuxième projet créé dans un même workspace).
Ce qui provoque des erreurs au niveau du build path :



Si c'est le cas, il suffit de les ajouter :
  - Dans « src/main » : new folder « java »
  - Dans « src » : new folder « test/java », et tant qu’on y est « test/resources »

3) Configuration du "pom.xml"


En ouvrant le fichier "pom.xml" on constate qu'il contient assez peu de chose.
Trop peu, puisqu'il n'y a même pas les dépendances aux libraires Servlet/JSP.

Il n'y a donc plus qu'à le compléter en fonction des besoins du projets

Exemples :

* Pour ajouter les JARs nécessaires aux Servlets 3.0 et au JSP 2.2 (Tomcat 7, Jetty 8, Java EE 6)
dans "dependencies" :

<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.0.1</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>javax.servlet.jsp-api</artifactId>
   <version>2.2.1</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>jstl</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
</dependency>

Pour forcer la version de Java  (ici Java 7)
dans "build/plugins"  :

<plugin>
   <artifactId>maven-compiler-plugin</artifactId>
   <version>3.0</version>
   <configuration>
      <source>1.7</source>
      <target>1.7</target>
   </configuration>
</plugin>

* Pour configurer la production du « war »
dans  "build/plugins" :

<plugin>
   <artifactId>maven-war-plugin</artifactId>
   <version>2.3</version>
   <configuration>
      <failOnMissingWebXml>false</failOnMissingWebXml>
   </configuration>
</plugin>

Après avoir enregistrer les modifications du « pom.xml » ,
faire " Maven / Update project… "
pour répercuter la configuration du « pom.xml » sur le projet Eclipse

Le projet doit finalement avoir la structure suivante :
Et il ne doit plus y avoir aucune erreur nul part.

4) Tester le fonctionnement 


- Test avec une JSP :
Lancer l’exécution comme s’il s’agissait d’un projet web WTP classique :
Run as / Run on server 
On arrive sur la page « Hello world » produite par la JSP « index.jsp »,
si on modifie cette JSP il suffit de rafraîchir la page pour prendre en compte les modifications (comme dans tout projet WTP).

- Test avec une servlet :
Créer une nouvelle servlet dans  « src/main/java » 
(avec les servlet 3.0 il n’est pas nécessaire de déclarer cette nouvelle servlet dans le web .xml, une annotation suffira)

Conclusion


Avec une installation Eclipse Kepler de base il est maintenant assez simple de gérer des projets web.
Pour ceux qui veulent aller un peu plus loin il ne reste plus qu'à créer ses propres archetypes Maven...

Pour plus d'informations :



lundi 29 octobre 2012

L’encapsulation ne résiste pas à l’introspection


L’introspection Java, basée sur la « Java Reflexion API »,  permet de découvrir la structure de n’importe quelle classe. Ce principe permet donc de connaitre tous les éléments constitutifs d’une classe (champs, constructeurs, méthodes, ...) et d'agir sur ces éléments. Tous développeurs Java connaissent les usages classiques de cette API, mais si vous lisez cet article jusqu'à la fin vous verrez qu'une utilisation poussée de l'introspection permet d'aller extrêmement loin, par exemple jusqu'à modifier la valeur de la constante "TRUE" de la classe "Boolean" !   Etonnant, non ?

Utilisation basique de l'introspection 

Un des principaux intérêts de la réflexion est de pouvoir récupérer dynamiquement les valeurs des champs et d’invoquer les méthodes d’un objet dont on ne sait rien et sans avoir besoin du code source. Ce qui permet aux frameworks et autres bibliothèques Java en tous genres de récupérer des informations à partir, par exemple, d’un nom symbolique.

Ainsi,  avec l’ Expression Language dans les JSP l’expression « ${employe.nom} » sera analysée, puis la méthode « getNom() » de l’objet nommé « employe » sera invoquée et le résultat inséré à la place de l’expression.

Donc l’introspection c’est pratique, c’est même indispensable et jusque là tout va bien…
Mais l’introspection ne se limite pas à la consultation des objets, il est également possible de changer la valeur des champs et d’invoquer des méthodes qui modifient les données d’un objet (typiquement en invoquant des « setters »).

Alors qu’en est-il  de la sécurité ? 

Par défaut, les principes de sécurité qui sont appliqués à l’introspection sont les mêmes que ceux qui régissent les droits d’accès aux champs et aux méthodes d’un objet quand on utilise une classe lors du développement.

Donc  les méthodes et les champs privés d’une classe ne sont pas accessibles.

Exemple 1 – Tentative de modification d'un champ « private »  :
Field field = null ;
try {
   field = Employee.class.getDeclaredField("salary"); // Champ "private"
} catch (SecurityException e) {
   e.printStackTrace();
} catch (NoSuchFieldException e) {
   e.printStackTrace();
}

try {
   field.setDouble(employee, 1234.56); // Tentative de modification
} catch (IllegalArgumentException e) {
   e.printStackTrace();
} catch (IllegalAccessException e) {
   e.printStackTrace();
}


L'exécution de ce code va provoquer une Exception :
IllegalAccessException : Class .... can not access a member of class .... with modifiers "private"
puisque le champ "salary" est "private"


Comment les frameworks font-ils pour valoriser des champs privés ?

Les ORM (JPA, Hibernate, etc.. )  réussissent pourtant à valoriser des champs privés après un accès à la base de données
public class Employee {
   @Id
   @Column(name="EMP_ID")
   private int id; // Champ valorisé par JPA
   @Column(name="NAME")
   private String name; // Champ valorisé par JPA
}

Et c’est la même chose pour l’injection de dépendance…
public MyClass {
   @Inject
   private MyResource resource; // Injection (affectation d'une instance)
}

Il y a évidemment une solution :  il suffit d’appeler la méthode
« setAccessible(true) » sur le champ concerné pour le déverrouiller et le rendre immédiatement accessible, c'est-à-dire modifiable.


Exemple 2 - utilisation de setAccessible :
field.setAccessible(true);
field.setDouble(employee, 1234.56); // Et la tout se passe bien

L’appel  à  « setAccessible() » supprime les contrôles d’accès aux champs, méthodes et constructeurs (méthode héritée de la classe AccessibleObject)



L’utilisation de « setAccessible() »  est soumise à l’autorisation du « SecurityManager »
(cf java.lang.SecurityManager), un objet qui définit la politique de sécurité d’une application.

Pour obtenir le SecurityManager s’il existe :
SecurityManager secManager = System.getSecurityManager() ;
Dans certains environnements particuliers un SecurityManager peut être présent, notamment pour tout ce qui concerne le code téléchargé (Applets, Java Web Start, etc… ).  Mais par défaut la JVM n’a pas de SecurityManager, ce qui permet notamment d’utiliser JPA et l’injection de dépendance sans aucun problème dans pratiquement tous les cas.


Et si le champ est « final » ?

En principe un champ « final » n’est pas modifiable à postériori… Mais avec la « reflexion API » c’est possible, modifier un champ « private final » se fait exactement comme pour un champ « private »
non « final »

Et si le champ est « final static » ?

Alors là ça change tout !
Il s’agit d’un champ porté par la classe et qui sert de constante, donc  la « reflexion API » a quelques scrupules à nous laisser le modifier à tout moment. Et donc, même avec un appel préalable à  « setAccessible(true) » une exception sera levée :
IllegalAccessException: Can not set static final …. field …. to … 
Et on se dit que c’est tant mieux, car ce serait un peut cavalier de modifier des constantes…

Hummm….  Pourtant en poussant la réflexion (c’est le cas de le dire) un peu plus loin on arrive à la conclusion suivante : c’est le « final » qui pose problème quand il s’applique à un champ « static ».
Et qu’est-ce qui matérialise cette caractéristique « final » ? C’est un des « modifiers » récupérable avec « getModifiers() ».

Exemple 3 - utilisation des "modifiers" :
int fieldModifiers = field.getModifiers(); 
if ( Modifier.isStatic(fieldModifiers) ) {
   if ( Modifier.isFinal(fieldModifiers) ) {
      // static et final
   }
}

Donc, si on supprime le « modifier »  « final » ça va passer ?   He bien  oui !

Ce qui veut dire qu’un champ qui était « private » peut devenir « public » ou perdre sa
caractéristique  « final » ?
Et oui, en effet…   Il suffit de modifier les « modifiers » du champ.

Comment modifier les « modifiers » d’un champ ?

Les « modifiers » sont stockés dans un champ « private » de type « int » de la classe « Field », il faut donc s’attaquer directement à cette classe ( Field ) pour rendre ce champ accessible et donc de  pouvoir ensuite le modifier.
On va donc introspecter et modifier les classes qui servent à l'introspection (oui, on pousse le bouchon un peu loin, mais on s'arrêtera là,  promis...).

Le principe est le suivant :
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true); // "modifiers" est maintenant modifiable
Une fois accessible, il suffit d’affecter la nouvelle combinaison de « modifiers » à ce champ
modifiersField.setInt(targetField, newModifiers ) ;
( des exemples complets sont fournis un peu plus loin )

Comment l’introspection remet en cause l’immuabilité des objets

En Java un attribut est immuable s’il est « private » et que la classe ne fournit aucune méthode permettant de le modifier.
Ainsi, depuis les premiers cours d’initiation à Java on nous a expliqué que les instances de « Boolean » et « String » par exemple étaient immuables. Et pourtant, en poussant l’introspection dans ses derniers retranchements il est tout à fait possible de modifier de type d’objets (voir les exemples ci-après)

Voici quelques exemples d’utilisation un peu « border line » de l’introspection qui démontrent qu'on peut aller très loin (trop loin ?)...

NB : Ces exemples sont potentiellement dangereux et n'ont pas vocation à être utilisés dans une application réelle.


Exemple A  – Modifier le contenu d’une instance de la classe "Boolean"

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * Modification d'une instance de Boolean avec la Reflexion API
 * Copyright (c) 2012 Laurent Guerin - Licence LGPL v3
 */
public class ChangeBoolean {

 public static void main(String[] args) {
  
  Boolean b1 = new Boolean(true) ;
  
  System.out.println(" b1  : " + b1 + ", b1.booleanValue() : " + b1.booleanValue() );
  
  try {
   changeValue( b1, false ) ;
  } catch (Exception e) {
   e.printStackTrace();
  }
  
  System.out.println(" b1  : " + b1 + ", b1.booleanValue() : " + b1.booleanValue() );  
 }

 /**
  * Change la valeur d'un booleen
  * @param instance du booleen a modifier 
  * @param newValue valeur a affecter
  * @throws Exception
  */
 public static void changeValue(Boolean instance, boolean newValue) throws Exception {

  // La valeur est portee par le champ "value" de la classe "Boolean"
  Field field = Boolean.class.getDeclaredField("value") ;
   
  int targetFieldModifiers = field.getModifiers();
  if ( Modifier.isFinal(targetFieldModifiers) ) System.out.println(" field is 'final' ");
  if ( Modifier.isPrivate(targetFieldModifiers) ) System.out.println(" field is 'private' ");
  // Le champ "value" est "final" et "private"
  
  field.setAccessible(true) ;

  System.out.println(" original value : " + field.get(instance) );
  System.out.println(" change value to : " + newValue);
  field.set(instance, newValue) ;
 }
}

Exemple B  – Modifier le contenu d’une instance de la classe "String"

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * Modification d'une instance de String avec la Reflexion API
 * Copyright (c) 2012 Laurent Guerin - Licence LGPL v3
 */
public class ChangeString {

 public static void main(String[] args) {
  
  String s = "Hello world !" ;
  String s2 = new String(s) ;
  
  System.out.println("s = " + s  + " s.hashCode = " + s.hashCode());
  System.out.println("s2 = " + s  + " s2.hashCode = " + s2.hashCode());
  System.out.println("s == s2 ?  " + ( s == s2 ) );
  System.out.println("s.equals(s2) ?  " + ( s.equals(s2) ) );
  
  try {
   System.out.println("Convert to uppercase...");
   toUpperCase( s ) ;
   System.out.println("s  = " + s  + " hashCode = " + s.hashCode());
   
   System.out.println("Change value ...");
   populate(s, "ABCDEFGHIJ") ;
   System.out.println("s = " + s  );
   
  } catch (Exception e) {
   e.printStackTrace();
  }
  
  System.out.println("s  = " + s  + " s.hashCode = " + s.hashCode());
  System.out.println("s2 = " + s2  + " s2.hashCode = " + s2.hashCode());
  System.out.println("s.equals(s2) ?  " + ( s.equals(s2) ) );
  System.out.println("s.equals('ABCDEFGHIJ') ?  " + ( s.equals("ABCDEFGHIJ") ) );
 }

 /**
  * Converti la chaine en majuscules
  * @param s 
  * @throws Exception
  */
 public static void toUpperCase ( String s ) throws Exception {

  // Les caracteres qui composent une String sont dans le champ "value" (private)  
  // qui pointe sur un tableaux de "char" 
  Field valueField = String.class.getDeclaredField("value");
  // Hash code de la chaine 
  Field hashField   = String.class.getDeclaredField("hash"); 
   
  int targetFieldModifiers = valueField.getModifiers();
  if ( Modifier.isFinal(targetFieldModifiers) ) System.out.println(" field is 'final' ");
  if ( Modifier.isPrivate(targetFieldModifiers) ) System.out.println(" field is 'private' ");
  
  valueField.setAccessible(true) ; 
  hashField.setAccessible(true) ;

  String sUpperCase = s.toUpperCase() ;
  char[] newValue = sUpperCase.toCharArray(); // Same array size => no pb

  valueField.set(s, newValue ); 
  hashField.setInt(s, newValue.hashCode()); // Hash code
  // La conversion en majuscules conserve le meme nombre de caracteres 
  // il n'y a donc rien d'autre a changer
 }
 
 /**
  * Change la valeur d'une chaine
  * @param s chaine a modifier
  * @param newString chaine a affecter
  * @throws Exception
  */
 public static void populate ( String s, String newString ) throws Exception {
  // Caracteres de la chaine
  Field valueField  = String.class.getDeclaredField("value");
  // Offset sur le tableau de char
  Field offsetField = String.class.getDeclaredField("offset");
  // Nombre de caracteres dans le tableau
  Field countField  = String.class.getDeclaredField("count");
  // Hash code de la chaine 
  Field hashField   = String.class.getDeclaredField("hash"); 
  
  valueField.setAccessible(true) ;
  offsetField.setAccessible(true) ;
  countField.setAccessible(true) ;
  hashField.setAccessible(true) ;

  // Affichage des valeurs d'origine 
  char[] value = (char[]) valueField.get(s);
  String sValue = new String(value);
  System.out.println("value  = '" + sValue + "' ( length = " + value.length + ", hashCode = " + s.hashCode() + " )" );
  System.out.println("offset = " + offsetField.getInt(s) );
  System.out.println("count  = " + countField.getInt(s) );
  System.out.println("hash   = " + hashField.getInt(s) );

  // Nouvelle chaine a affecter 
  String newValue = newString ;
  valueField.set(s, newValue.toCharArray() );
  // Le nombre de caracteres change => mettre a jour les autres informations 
  offsetField.setInt(s, 0); // Offset : on demarre a 0
  countField.setInt(s, newValue.length()); // Nombre de caracteres
  hashField.setInt(s, newValue.hashCode()); // Hash code  
 }
}


Exemple C  – Modifier la valeur de la constante "TRUE" de la classe "Boolean"
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * Modification d'une constante de la classe Boolean avec la Reflexion API
 * Copyright (c) 2012 Laurent Guerin - Licence LGPL v3
 */
public class ChangeBooleanTRUE {

 public static void main(String[] args) {
  System.out.println("=== AVANT : ");
  System.out.println(" Boolean.TRUE  : " + Boolean.TRUE  );
  System.out.println(" Boolean.FALSE : " + Boolean.FALSE );
  System.out.println(" Boolean.valueOf(true)  : " + Boolean.valueOf(true)  );
  System.out.println(" Boolean.valueOf(false) : " + Boolean.valueOf(false) );
  
  try {
   changeTRUEConstant( false ) ;
  } catch (Exception e) {
   e.printStackTrace();
  }
  
  System.out.println("=== APRES : ");
  System.out.println(" Boolean.TRUE  : " + Boolean.TRUE  ); // false (!)
  System.out.println(" Boolean.FALSE : " + Boolean.FALSE );
  System.out.println(" Boolean.valueOf(true)  : " + Boolean.valueOf(true)  ); // false (!)
  System.out.println(" Boolean.valueOf(false) : " + Boolean.valueOf(false) );
 }

 
 /**
  * Change la valeur de la constante TRUE (!) 
  * @param newValue
  * @throws Exception
  */
 public static void changeTRUEConstant( boolean newValue ) throws Exception {

  // La constante TRUE ( final static ) 
  Field field = Boolean.class.getDeclaredField("TRUE") ;
  
  field.setAccessible(true) ;
  
  int fieldModifiers = field.getModifiers();
  
  if ( Modifier.isStatic(fieldModifiers) ) {
   if ( Modifier.isFinal(fieldModifiers) ) {
    // Ce champ est "final static" : il faut supprimer "final"
    removeFinalModifier(field);
   }
  }
  // Affectation de la nouvelle valeur 
  field.set(null, newValue) ;
 }
 
 /**
  * Supprime le modifier "final" du champ 
  * @param targetField
  * @throws Exception
  */
 public static void removeFinalModifier(Field targetField) throws Exception {

  Field modifiersField = Field.class.getDeclaredField("modifiers");
  
  modifiersField.setAccessible(true); // Les "modifiers" sont maintenant accessibles

  int targetFieldModifiers = targetField.getModifiers();
  
  modifiersField.setInt(targetField, targetFieldModifiers & ( ~Modifier.FINAL ) ) ; // Le champ n'est plus "final"
  
 }
}

Conclusion :  introspection = no limit !

En  conclusion, avec la « Java Reflexion API »  on peut pratiquement tout modifier dynamiquement, y compris des données réputées immuables. Ce qui ouvre des perspectives intéressantes mais potentiellement dangereuses. L’introspection est donc un outil puissant, mais à manipuler avec précaution.



mardi 28 août 2012

Java - Optimisation et performance


Présentation de Charlie Hunt "Extreme Performance with Java" sur InfoQ  (mythes et réalités)
http://www.infoq.com/presentations/Extreme-Performance-Java


Série d'articles de Java World sur la JVM et ses performances

- Premier article d'une série consacrée aux performances Java
"JVM performance optimization, Part 1: A JVM technology primer"
Que fait réellement la JVM ? Comment se comporte le Garbage Collector ?  etc...
http://www.javaworld.com/javaworld/jw-08-2012/120821-jvm-performance-optimization-overview.html

- La suite : le compilateur (2eme partie )
"JVM performance optimization, Part 2: Compilers"
Compilation statique/dynamique, bytecode, inlined methods, ...
http://www.javaworld.com/javaworld/jw-09-2012/120905-jvm-performance-optimization-compilers.html

- 3ème partie : garbage collection
"JVM performance optimization, Part 3: Garbage collection"
http://www.javaworld.com/javaworld/jw-10-2012/121010-jvm-performance-optimization-garbage-collection.html

- 4ème partie : algorithme "C4" du GC
"JVM performance optimization, Part 4: C4 garbage collection for low-latency Java applications"
http://www.javaworld.com/javaworld/jw-11-2012/121107-jvm-performance-optimization-low-latency-garbage-collection.html

- 5ème partie : un peu de provocation dans le titre
"JVM performance optimization, Part 5: Is Java scalability an oxymoron?" 
http://www.javaworld.com/javaworld/jw-03-2013/130301-jvm-performance-optimization-java-scalability.html

Autres liens sur la JVM :