JAVA et JVM Introduction Jean-Jacques LE COZ Le langage JAVA Langage de programmation orienté objet Créateurs James Gosling Patrick Naughton Date de création officielle 23 mai 1995 Origine ● Projet Stealth, puis Green Project 1990 Le langage C++ pas satisfaisant ● Car orientations du projet vers l'embarqué Objectifs ● ● ● ● Sécurité Portabilité Environnement distribué Multi-threading Le langage ● Syntaxe proche du C++ ● Indépendant de la plateforme Byte code ● Mécanisme de ramasse-miettes Garbage collector ● Méta-données Réflexion (accès dynamique) ● Orientations réseau Trois cadriciels ● JAVA SE Standard Edition ● ● ● JDK (développement) JRE (exécution) JAVA EE Enterprise Edition ● ● XML, EJB, Web, Services Web JAVA ME Micro Edition Commandes de base ● Compilation Commande javac ● Exécution Commande java ● ● Test de version : java -version Création et exécution de paquetages de distribution Commande jar Paquetages Java ● JAR JAVA SE JAVA EE EJB ● WAR JAVA EE Web avec IHM ● EAR Entreprise ● Composition EJB (jar) + Web (war) Outils de gestion de projet ● Ant Standard de fait Même concept que Makefile d'UNIX Avec la portabilité en plus ● Maven Au dessus de Ant Orienté génération d'applications Fonctionne en réseau Variables d'environnement ● JAVA_HOME Lieu d'installation de la distribution JDK ● JRE_HOME Lieu d'installation de la distribution JRE ● CLASSPATH Lieu d'installation des librairies Java ● ● Nécessaires à la compilation Nécessaires à l'exécution Machine virtuelle Java Introduction JVM ● Java Virtual Machine Instance de JRE ● Interprète et exécute le bytecode Java ● Spécifique à chaque plateforme Linux, UNIX (AIX, SOLARIS) MacOS (Apple) Windows, Vista (Microsoft) z/OS (IBM) Activité de la JVM ● Exécution du bytecode ● Compilation à la volée ● Gestion de la mémoire Allocation mémoire avec l'OS Allocation JAVA (HEAP) Nettoyage de la mémoire (Garbage) Fuite mémoire ● Objets dans le mauvais contexte ● Le GC préfère les objets à vie courte public class Foo { private String[ ] names; public void doIt(int length) { if (names == null || names.length < length) names = new String[length]; populate(names); print(names); } Public class Foo { public void doIt(int length) { String[ ] names = new String[length]; populate(names); print(names); } Mythes sur la gestion mémoire ● Mettre à null les références aide le GC En revanche le code est plus clair Peut améliorer les performances ● Appeler System.gc() ● Éviter si possible les allocations d'objets Au contraire la JVM est très rapide dans la création des objets Portabilité ● Concept « write once, run anywhere » ● ● Les versions de JVM pour plateformes sont spécifiques Le code n'a pas besoin d'être recompilé Attention à la compilation juste à temps ● ● JIT (Just in Time) Java SUN HotSpot JIT: just-in-time ● ● Compilation à la volée encore appelée traduction dynamique Combine les avantages de la compilation native et du bytecode. Lorsque le bytecode est exécuté, le compilateur le traduit en code machine natif ● Grâce à la librairie Java Native Interface Le bytecode déployé reste portable JAVA HotSpot VM ● Optimisation flexible En fonction du bytecode le plus utilisé ● JIT Compilateur Le code natif issu de la compilation à la volée est stocké en cache ● Garbage Collector amélioré ● Synchronisation rapide des threads JAVA et méta-données ● La JVM stocke les méta-données relatives aux objets ● La JVM expose des API de supervision ● Intérêts Introspection dynamique de la JVM Embarquement d'agents de supervision Modification dynamique du bytecode Support de langages ● JavaFX ● Ruby avec JRuby ● JavaScript avec Rhino ● Python avec Jython ● Groovy ● Scala ● Clojure Licence ● Propriété de SUN MICROSYSTEM Gratuité, code source ● Depuis la version 1.5 (Tiger) Développement en mode JCP ● Java Community Process Spécifications sous forme JSR ● ● Java Specification Requests Depuis 2007 Mode communautaire OPENJDK (GPL) Éditeurs ● SUN MICROSYSTEMS ● IBM ● BEA (Oracle) ● OpenJDK Communauté libre avec possibilité de donation de code et d'enrichissements ● ● Apple SUN, IBM, REDHAT, UBUNTU, ... Oracle ● ● La société Oracle a racheté en avril 2009 Sun Microsystems Cette acquisition a été acceptée par l'Union Européenne début 2010 Redwood Shores, CA - April 20, 2009 Oracle Corporation (NASDAQ: ORCL) and Sun Microsystems (NASDAQ: JAVA) announced today they have entered into a definitive agreement under which Oracle will acquire Sun common stock for $9.50 per share in cash. The transaction is valued at approximately $7.4 billion, or $5.6 billion net of Sun’s cash and debt. “We expect this acquisition to be accretive to Oracle’s earnings by at least 15 cents on a non-GAAP basis in the first full year after closing. We estimate that the acquired business will contribute over $1.5 billion to Oracle’s non-GAAP operating profit in the first year, increasing to over $2 billion in the second year. This would make the Sun acquisition more profitable in per share contribution in the first year than we had planned for the acquisitions of BEA, PeopleSoft and Siebel combined,” said Oracle President Safra Catz. JVM À l'intérieur de la JVM Zones d'exécution de la JVM ● Données associées à la JVM Création au démarrage de la JVM Destruction à l'arrêt de la JVM ● Données associées aux Thread Création au démarrage d'une thread Destruction à la fin d'une thread Zones d'exécution de la JVM ● JVM Supporte de nombreuses thread ● Registre pc register (program counter) ● ● Un par thread Stack Chaque thread possède son stack Créé en même temps que la thread Contient des pages mémoire (frame) Zones d'exécution de la JVM ● Frame Contient : ● ● ● ● Les variables locales et résultats partiels Données pour liens dynamiques Valeurs de retour des méthodes Exceptions Allouée dans un tas (Heap) ● Taille du stack contenant les frame Option -oss au lancement de la JVM Zones d'exécution de la JVM ● Heap Partagé entre threads Gestion de la mémoire du Heap ● ● Ramasse-miette (Garbage Collector) Taille du Heap contenant les stacks Option -Xms (taille initiale) Option -Xmx (taille maximum) ● Exception OutOfMemeoryError Tas et ramasse miettes HEAP garbage Racine des références garbage garbage garbage Garbage Collector ● Recherche des objets non référencés Depuis les racines des applications ● Thread stacks, static fields, registers Parcours le tas en partant de la racine ● ● ● Visite chaque objet vivant Tous les objets non atteignables sont détruits (garbage) Multiplicité de solutions Algorithmes (différents selon les générations d'objet) Utilité du ramasse miette ● Renforcement de la fiabilité Pas de « fuite » mémoire Pas de pointeur « dangling » Augmente la productivité du développeur ● ● Pas de programmation de la mémoire Possibilité qu'un objet vivant soit référencé mais pas utilisé Rétention d'objets (OutOfMemoryError) ● Exemple: trop de singletons Statistiques ● La plupart des objets ont une vie courte 90%* ● Les vieux objets ont tendance à vivre très longtemps 10% Loi des 90/10 Inconvénient du ramasse miette ● L'activité du ramasse miette provoque des pauses dans l'exécution des applications Zones d'exécution de la JVM ● Le tas (heap) est divisé en 3 espaces Zone jeune (Young space) ● ● Zone Eden et deux espaces Survivor Partie virtuelle Zone vielle ● ● Partie Tenured ou old Partie virtuelle Zone permanente ● ● Partie Perm Partie virtuelle Zones d'exécution de la JVM ● La zone jeune Young space ● Pour les objets récents (enfants) Création dans la zone Eden ● Deux espaces Survivor Un occupé par les objets, l'autre libre Le Survivor libre sert d'espace de copie ● Le GC y copie les objets référencés de l'Eden et du Survivor occupé Partie virtuelle ● Zone tampon Zones d'exécution de la JVM ● La zone vielle Les objets à longue durée de vie sont copiés du Survivor dans le old space Tenured ou old space ● Objets à longue durée de vie (ancêtres) Partie virtuelle ● Zone tampon Zones d'exécution de la JVM ● La zone permanente Perm space ● ● Contient toutes les données statiques Le code binaire de chaque classe chargée Partie virtuelle ● Zone tampon Les espaces « Génération » NOUVEAUX OBJETS PERM OLD | 64MB | | | | JVM Old SS#1 | SS#2 New / Young Utilisé par l'application Espace total du tas (HEAP) EDEN | | | Fonctionnement du Garbage Collector ● Minor Garbage Collection Déclenché quand le Eden est plein Parcours le Eden et le Survivor courant ● ● ● Déplacement des objets référencés dans le Old ou dans l'autre Survivor Les autres objets sont détruits (garbage) Un nouveau Tenured age est calculé Estampille Fonctionnement du Garbage Collector ● Major Garbage Collection Déclenché quand le Old est plein Tous les espaces sont nettoyés (garbage) Toutes les autres activités sont suspendues Zones d'exécution de la JVM ● Aire pour les méthodes Method Area Partagée entre les threads Analogue aux segments mémoire UNIX Stockage ● Les structures pour les classes Runtime Constant pool Code des méthodes Champs et données des méthodes ● Non paramétrable par défaut Zones d'exécution de la JVM ● Runtime Constant Pool Un par interface ou classe Représentation de la table Constant pool du bytecode de chaque classe ou interface Zones d'exécution de la JVM ● Native Method Stack Pour supporter les méthodes écrites dans un autre langage que Java ● Exceptions StackOveFlowError OutOfMemoryError Ligne de commande et JVM ● Options au lancement de la JVM java -option nom du programme java -X:option nom du programme java -XX:option nom du programme java -Xoption nom du programme ● Ces options peuvent se conjuguer ● Très grand nombre d'options Mais tuning délicat Options de base ● Verbeux et version Option -verbose Option -version ● CLASSPATH Option -cp ou -classpath ● Debug De la compilation avec option -g Debug distant à l'exécution : -Xdebug Options de base ● Mode de lancement Client : java -client programme Serveur : java -server programme ● Tuning « Ergonomics » (server class) Automatique Machine avec 2 CPU Au moins 2GB de mémoire ● Compilation avec option -server ● -XX:+UseParallelGC ● -Xms taille initiale heap: 1/64 RAM ● -Xmx taille maxi heap: ¼ RAM Options de base ● Options de mémoire Tas (heap) ● ● ● Option -Xms pour taille initiale Option -Xmx pour taille maximale Ratios de mémoire pour le tas En fonction de ces ratios ● Pourcentage de mémoire ● La JVM augmente ou diminue le tas ● Après le passage du GC Option -XX:MaxHeapFreeRatio Option -X:MinHeapFreeRatio Options de base ● Définition de propriétés système Option -Dpropriete=valeur ● Exécution de paquetages exécutables Option -jar ● Ramasse-miettes Verbeux ● Option -verbose:gc Journalisation ● Option -Xloggc:fichier Ramasse-miettes ● Gestionnaire de la mémoire ● Évite les fuites mémoire ● Thread déclenché en basse priorité ● Il doit gérer des milliers d'objets ● Gros impact sur les performances ● Peut-être non lancé (versions JVM <= 1.4) Peut être invoqué dans une application ● System.gc() Ramasse-miettes ● Option de journalisation Option -Xloggc:fichier Structure du journal ● ● ● ● ● ● ● R(n) = T(n): [ <GC> HB->HE(HC), D] R(n) enregistrement GC T(n) Temps HB quantité de heap utilisé avant GC HE quantité de heap utilisé après GC HC total de heap D durée du cycle Ramasse-miettes ● Garbage collector Pour libérer de la mémoire Outil de parcours de graphes d'objets ● Suppression des objets non référencés Plusieurs algorithmes ● Minor Collection Recopie les « vivants » vers le Survivor libre ● Major Collection (algorithme Mark-Sweep-Compact) Parcours de tout les « morts » et marquage Second parcours pour défragmentation Ramasse-miettes ● A chaque exécution du GC Interruption de l'application ● Options du Garbage collector -Xms -Xmx -XX:NewRatio= ● Rapport entre old et young spaces -XX:SurvivorRatio= ● Rapport entre Eden et Survivor Ramasse-miettes ● Options du Garbage collector -Xincgc active le GC incrémental ● ● Le GC effectue une partie de Major Collection à chaque Minor Collection Élimine l'attente lors des Major Collection -XX:+UseParallelGC ● -XX:ParallelGCThreads= -XX:+UseConcMarkSweepGC ● -XX:+UseParNewGC JVM tuning introduction Optimisation ● Bonnes performances de base pour les JVM 1.6 Pas besoin de tuning ● Serveur Grand tas (heap), parallèle GC, compilateur HOTSPOT serveur ● Client Petit tas, séquentiel GC et compilateur HOTSPOT client Diagnostique ● GC Option -verbose:gc Option -XX:+PrintHeapAtGC ● Fichier de sortie Option -Xrunhprof:heap=sites,cpu=samples,dept h=10,thread=y,doe=y ● Option -XX:+HeapdumpOutOfMemoryError -XX:HeapDumpPath=C:\OOM.txt Solutions ● Mémoire Taille du tas (HEAP) ● espaces young et tenured pas perm Option -ms -Xms Option -mx -Xmx (défaut :64mb) Pour l'espace Perm ● Option -XX:PermSize=256 -XX:MaxPermSize=256m JAVA Java Pratique Les commandes ● Liste des commandes java -Xprof ● Version de JVM java -version ● Compilation javac programme-source ● Exécution java programme-byte-code Les archives ● Archive jar Librairies JAVA SE Composants d'entreprise (EJB) ● Archive war Applications Web Services Web ● Archive ear Applications d'entreprise (WEB+EJB) Archive jar ● Construction jar -cvf ● Extraction jar -xvf ● Introspection jar -tvf ● Exécution java -jar archive Archive jar et méta-données ● Le fichier manifest Contient des informations sur l'archive Les méta-informations permettent de définir les utilisations possibles de l'archive Construction avec manifest ● jar -cvfm Construction sans manifest ● jar -cvfM Le fichier manifest ● Contenu Pairs attribut : valeur ● Lieu de stockage Sous le répertoire META-INF/ ● Chemin et nom par défaut META-INF/MANIFEST.MF Variables d'environnement ● JAVA CLASSPATH ● JAVA et système JAVA_HOME JRE_HOME ● Système PATH CLASSPATH ● Deux fonctions Chemin des ressources interne Chemin des ressources externes ● Deux emplois Compilation et exécution ● Commande export CLASSPATH=ressources Option -cp avec javac et java VisualVM introduction Introduction ● Produit disponible depuis la version 1.6 ● Écrit en JAVA ● Interface Homme-machine graphique ● Fonctionnalité Organise et présente sous une forme graphique les informations relatives à l'exécution d'une application JAVA au sein d'une JVM JVM locale et distante Informations traitées ● Thread Capture des processus fins actifs ● Heap Capture de l'état des objets dans le tas ● Profiler Analyse des performances Utilisation mémoire ● Snapshot Utilisation ● Démarrage $JAVA_HOME/bin/jvisualvm ● Mode local Capture directement les applications lancées avec une JVM 1.6 et le même utilisateur ● Mode Distant Capture avec le protocole JMX les applications lancées avec une JVM 1.6 Utilisation ● Autres cas Application lancées avec une JVM < 1.6 Applications lancées par un autre utilisateur Nécessite de lancer les applications avec les options suivantes : java -Dcom.sun.management.jmxremote.port=3333 \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.authenticate=false \ application Extensions ● Plugins Installation de fonctionnalités supplémentaires par le menu JMX Introduction JMX ● Java Management Extension (JMX) Standard de la plateforme JAVA SE Gestion de ressources (monitorage) ● Applications, appareils et services Basé sur un agent serveur ● ● MBean server MXBean Connecteurs standards ● JMX Connectors Protcoles JMX ● Plusieurs protocoles SNMP (Simple Network Management Protocol) JAVA RMI Protocoles propriétaires API JMX ● Classes ManagementFactory ● Méthode getPlatformMBeanServer() MBeanServer ● Méthode registerMBean(mbean, nom) Exemple public interface HelloMBean { public void sayHello(); public int add(int x, int y); public String getName(); } public int getCacheSize(); public void setCacheSize(int size); Exemple public class Hello implements HelloMBean { public void sayHello() { System.out.println("hello, world"); } public int add(int x, int y) { return x + y; } public String getName() { return this.name; } public int getCacheSize() { return this.cacheSize; } public synchronized void setCacheSize(int size) { this.cacheSize = size; System.out.println("Cache size now " + this.cacheSize); } private final String name = "Reginald"; private int cacheSize = DEFAULT_CACHE_SIZE; private static final int DEFAULT_CACHE_SIZE = 200; } Exemple public class Main { public static void main(String[] args) throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("com.example:type=Hello"); Hello mbean = new Hello(); mbs.registerMBean(mbean, name); } } System.out.println("Waiting forever..."); Thread.sleep(Long.MAX_VALUE); Exemple Exécution : java -Dcom.sun.management.jmxremote Puis lancement de visualvm Main