Ceci est un extrait électronique d'une publication de
Diamond Editions :
http://www.ed-diamond.com
Ce fichier ne peut être distribué que sur le CDROM offert
accompagnant le numéro 100 de GNU/Linux Magazine France.
La reproduction totale ou partielle des articles publiés dans Linux
Magazine France et présents sur ce CDROM est interdite sans accord
écrit de la société Diamond Editions.
Retrouvez sur le site tous les anciens numéros en vente par
correspondance ainsi que les tarifs d'abonnement.
Pour vous tenir au courant de l'actualité du magazine, visitez :
http://www.gnulinuxmag.com
Ainsi que :
http://www.linux-pratique.com
et
http://www.miscmag.com
Metadatas
La fonctionnalité metadata permet
d’associer des données additionnelles à
des classes, des interfaces, des méthodes
ou des attributs Java.
Ces données additionnelles, appelées
"annotations", peuvent être lues par le
compilateur Javac (ou d’autres outils)
et peuvent être stockées dans le fichier
class
et être appelées à l’exécution grâce
à l’API de réflexion Java.
Grâce aux metadatas, la plate-forme
Java permet à des outils tiers d’utiliser la
même infrastructure commune et donc de
réduire les efforts pour le développement
et le déploiement.
Un outil peut utiliser les metadatas pour
générer du code source supplémentaire
ou pour fournir des informations de
débuggage par exemple. C’est une forme
de Attribute Oriented Programmation
comme le fait XDoclet sur les tags
JavaDocs.
D’ailleurs Java 1.5 fournit un processeur
d’annotation appelé « apt ». Apt inclut un
ensemble de nouvelles API de réflexion
et supporte l’infrastructure pour gérer les
annotations.
Grâce aux metadatas (et apt), de
nombreuses étapes de répétition de
code peuvent être remplacées par des
tags. Par exemple, l’interface Remote
nécessaire lorsque vous accédez à un
service JAX-RPC peut être générée avec
les metadatas :
Alors qu’en Java 1.4, on aurait déclarer
notre interface explicitement :
Les nouveautés de
Java 1.5 Tiger
Par :: Jean-Baptiste Onofré
Depuis ses débuts, le langage Java n’a cessé d’évoluer
et introduit beaucoup de nouvelles fonctionnalités surtout
du côté serveur avec J2EE. Aujourd’hui, c’est une évolution
majeure qui voit le jour avec la sortie de la nouvelle version
du langage : Java 1.5, nom de code « Tiger ». Cette nouvelle
version rassemble des API développées précédemment
en dehors du JDK et introduit des nouvelles notations et
techniques de programmation. Faisons ensemble un tour
d’horizon des nouveautés de cette nouvelle version.
Les motivations
de Java 1.5
Les motivations de Java 1.5 peuvent se
résumer en quatre points :
Facilité de développement.
Performance et évolutivité.
Monitoring et manageabilité.
Client desktop.
Le JCP (Java Community Process) a
établi une liste de 15 spécifications JSR
regroupant plus de 100 changements
majeurs dans le langage.
On remarque bien l’importance de cette
nouvelle version à la fois dans ses
fonctionnalités pour le développeur mais
aussi pour l’utilisateur final.
Nouveautés du langage
pour faciliter le
développement
Nous allons voir ici les nouveautés
du langage qui facilitent la vie du
développeur.
Ces nouveautés sont :
Les types génériques.
Les metadatas.
L’autoboxing.
La nouvelle notation des iterators
(loop).
Les types énumérés.
Les imports statiques.
Le format d’écriture des entrées/
sorties « à la C ».
Les arguments variables.
Les utilitaires de concurrence.
La génération d’interface RMI
simplifiée.
Ces changements sont regroupés dans
trois spécifications JSR :
JSR-201 regroupe la nouvelle
notation des iterators, les types énumérés,
les imports statiques et l’autoboxing.
JSR-175 présente les spécifications
des metadatas.
JSR-14 décrit les types génériques.
Commençons la description de chaque
nouveauté.
12
News
public class Ping {
public @remote void ping() {}
}
Types génériques
Les types génériques sont tout
particulièrement utiles dans les collections.
L’API Collection fournit différents types de
listes comme les
LinkedList
, les
ArrayList
ou les
HashMap
qui peuvent être utilisées
pour stocker différents types d’objets. Par
exemple, avec Java 1.4, pour créer une
liste et stocker un objet à l’intérieur, il faut
faire :
Le cast de la dernière ligne est un cast
de type qui va pouvoir être évité avec les
types génériques.
Le problème vient du fait que l’API
Collection de Java 1.4 utilise la classe
« object » pour le stockage de la
Collection, ce qui signifie que le type ne
peut pas être déterminé au moment de la
compilation.
Si par exemple, vous attendez un objet
de type
Integer
, vous allez caster avec
(Integer)
, mais si l’objet inséré n’est
pas de type
Integer
(ce qui est tout à fait
possible puisque tous les objets en Java
héritent de la classe object), vous aurez
une ClassCastException à l’exécution.
Désormais avec les types génériques,
vous n’avez plus besoin de caster et vous
êtes sûrs que votre liste contient bien que
des objets du type que vous attendez :
Le développeur a juste à préciser le type
avec la notation
<>
.
Les casts de type ne sont plus nécessaires
et désormais, si par exemple vous essayez
d’insérer un objet
String
dans cette liste,
l’erreur sera détectée au moment de la
compilation (et pas à l’exécution).
Vous pouvez également définir vos
propres API utilisant les types génériques.
Pour cela, le mieux est de commencer par
jeter un oeil à l’implémentation de java.
util.Collection.
Autoboxing et auto-unboxing
des types primitifs
La conversion entre types primitifs
(comme
int
,
boolean
, etc. et leur
équivalent object comme
Integer
,
Boolean
, etc.) peut nécessiter du code
supplémentaire tout spécialement dans
un contexte de Collection. L’autoboxing et
l’auto-unboxing des types primitifs permet
de réduire significativement la quantité de
code à écrire pour les conversions.
Typiquement, voilà le code qu’il fallait
fournir pour la conversion de
Integer
vers
int :
On remarque que pour l’ajout dans la liste,
on doit explicitement créer l’objet avec
new Integer
et que pour la récupération
de la valeur, on fait appel à
intValue
pour revenir au type
int
. Grâce à l’auto-
boxing, ces manipulations sont faites
automatiquement :
Les
new Integer
et
intValue
ont disparu :).
Nouveau iterator
La classe
Iterator
est très utilisée dans
l’API Collection. Elle fournit un mécanisme
pour itérer dans une collection. La
nouvelle notation remplace l’itérateur
quand vous voulez simplement traverser
une collection. Le compilateur génère un
code d’itération nécessaire ainsi que les
casts nécessaires. Avec Iterator de Java
1.4, on fait :
A présent, on a une nouvelle notation
pour itérer :
Types énumérés
Un nouveau type voit le jour :
enum
. Il vous
permet de stocker une énumération de
constantes (statiques et finales) :
Import statique
L’import statique vous permet de
référencer une constante statique d’une
classe sans avoir besoin d’hériter de la
classe. Par exemple, à la place de faire
BorderLayout.CENTER
chaque fois que
vous ajoutez un component, vous pouvez
directement faire
CENTER
:
Sorties formatées
A présent, les développeurs peuvent
utiliser les sorties formatées comme
avec la fonction
printf
du langage C.
La majorité des formatés du langage C
est présente, plus quelques spécifiques
à Java notamment pour les Dates et les
BigInteger. Vous pouvez vous référer à la
classe
java.util.Formatter
. Le caractère
Unix
\n
est bien sûr accepté mais pour des
raisons de portabilité, il est recommandé
d’utiliser le standard Java
%n
.
Entrées formatées
Comme nous avons les sorties formatées
« à la C », nous avons l’équivalent côté
entrées. Java 1.5 fournit une API
Scanner
qui permet de lire des données à partir
de la console ou de n’importe quel flux
d’entrée. Les méthodes
next
et
nextInt
sont bloquantes si aucune donnée n’est
récupérée :
Arguments variables
Les arguments variables sont une
fonctionnalité permettant de passer des
arguments multiples comme paramètre
de méthodes. Il suffit d’utiliser la notation
...
pour que la méthode accepte une liste
d’arguments et utilise un nombre aléatoire
d’arguments. Ainsi, il n’est plus nécessaire
de fixer le nombre d’arguments :
Utilitaires de gestion de
concurrence
Le développement de l’API de gestion de
concurrence a débuté avant le Roadmap
de Java 1.5.
13
News
Les nouveautés de Java 1.5 Tiger
public interface PingI extends Remote {
public void ping() throws RemoteException;
}
public class Ping implements PingI {
public void ping() {}
}
ArrayList list = new ArrayList();
list.add(0, new Integer(42));
int total = ((Integer)list.get(0)).intValue();
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = list.get(0).intValue();
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = (list.get(0)).intValue();
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, 42);
int total = list.get(0);
ArrayList<Integer> list = new ArrayList<Integer>();
for(Iterator i = list.iterator(); i.hasNext();) {
Integer value = (Integer)i.next();
}
ArrayList<Integer> list = new ArrayList<Integer>();
for(Integer i:list) { ... }
public enum FeuDeSignalisation { rouge, orange, vert };
import static java.awt.BorderLayout.*;
getContentPane().add(new JPanel(), CENTER);
System.out.printf(„Newline %n“);
System.out.printf(„%s %5d%n“,user,total);
Scanner s = new Scanner(System.in);
String param = s.next();
int value = s.nextInt();
s.close();
void argumentreader(Object ... args) {
for(int i = 0; i < args.length; i++) {
System.out.println(args[i].toString());
}
}
argumentreader(„Hello“, „World“);
14
News
En effet, cette API est décrite dans la
spécification JSR-166 dirigée par Doug
Lea. Elle a donc été tout naturellement
incluse dans la Java 1.5.
Cette API permet une abstraction du
modèle de thread Java incluant les
executors, un framework de thread task,
des files d’attente de threads, les timers,
les locks (atomiques ou pas) et des
primitives de synchronisation.
Ainsi la programmation de sémaphores
est facilitée. Par exemple, désormais il est
possible de faire un wait sur un sémaphore
permettant de contrôler l’accès à un bloc
de code. Les sémaphores sont plus
souples et peuvent permettre l’accès à
plusieurs threads concurrents (bien sûr,
il faut que vous testiez le lock avant de
l’acquérir dans vos threads, ça ne se fait
pas encore tout seul :)). Je vous invite à
regarder le package java.util.concurrent
pour plus d’informations :
Il était une fois RMIC
Lorsque vous faites de la programmation
RMI (Remote Method Invocation), vous
avez le mécanisme que j’avais expliqué
dans l’article « Jboss »[1] : génération
du stub côté client qui est un proxy
embarquant les fonctionnalités réseau,
transfert réseau, skeleton côté serveur
qui est la même chose que le stub mais
côté serveur.
Dans un contexte J2EE, c’est le serveur
d’application qui s’occupe de la génération
des stubs et des skeletons. Mais lorsque
vous faites du RMI hors contexte J2EE,
il vous faut générer le stub de votre côté
(le côté client). Pour cela, vous deviez
faire appel à RMIC qui était un outil de
compilation RMI.
Désormais, avec l’utilisation des proxies
dynamiques, vous n’avez plus besoin de
RMIC : les informations fournies dans le
stub peuvent désormais être découvertes
à l’exécution.
Performances, évolutivité
et management
Amélioration des
performances
On reproche souvent à Java sa lenteur
et sa consommation ressource (même si
les choses se sont beaucoup améliorées
depuis Java 1.2). Java 1.5 s’est fixé des
objectifs de performance sans équivalent
et notamment au lancement.
Une nouveauté intéressante est
l’introduction du partage des données
de classe entre JVM. Cette technologie
permet à plusieurs JVM de partager les
mêmes données read-only, mais aussi de
permettre un démarrage plus rapide en
permettant le pre-packaging des classes
bas niveau de la JVM. Ainsi les nouvelles
JVM créées utilisent des données déjà
chargées en mémoire et sont donc
plus rapides. De nouvelles options
de paramétrage du heap Java voient
également le jour dans Java 1.5.
Désormais, deux nouveaux paramètres
permettent de spécialiser le comportement
de la JVM en fonction de l’application :
Le Maximum Pause Time Goal (option
-XX:MaxGCPauseMillis=nnn
) représente
le temps d’arrêt de l’application lorsque
le Garbage Collector est appelé. Si le
Garbage Collector met plus de temps
que le Maximum Pause Time Goal
pour s’exécuter, ce dernier est arrêté et
l’application reprend la main.
Le Throughput Goal (option
-XX:
GCTimeRatio=nnn
) mesure le temps occupé
par le Garbage Collector par rapport au
temps total. Ainsi, vous pouvez limiter
le temps passé en Garbage Collection
(le ratio est calculé par
1/(1 + nnn)
).
Ainsi, si vous précisez un ratio de 19 (
-
XX:GCTimeRatio=19
), cela signifie qu’au
maximum, vous allez passer 5% du temps
d’exécution dans le Garbage Collector.
Monitoring et management
Je vous avais déjà présenté JMX (Java
Management eXtension, spécification
JSR-160) dans l’article sur JBoss.
JMX permet de monitorer et manager
des périphériques ou applications
JMX-compliants. Désormais, JMX est
directement inclus dans la JVM ce qui
vous permet de monitorer et de manager
la JVM elle-même.
Dans la plate-forme Java, le monitoring
et le management sont un des points clef
de ce qu’on appelle RAS : Reliability,
Availability, Serviceability.
Désormais, vous disposez d’une API
dédiée au monitoring et au management.
Vous pouvez donc monitorer/manager
votre JVM directement dans du code ou
en utilisant un adaptateur JMX (client
distant ou console Web).
Par exemple, nous pouvons démarrer une
JVM avec le support d’une console JMX
sur un port donné :
Une autre possibilité est de monitorer
directement dans votre code. Voilà
comment afficher l’usage détaillé du heap
de la JVM :
Profiling
Java 1.5 inclut une API de profiling
appelée JVMTI. Cette API est spécifiée
dans la JSR-163, l’objectif initial était
de refondre les interfaces de profiling.
Au final, l’API couvre beaucoup d’autres
choses comme le profiling, le debugging
et des outils d’analyse de code.
L’implémentation inclut un mécanisme
d’instrumentation du bytecode appelé
JPLIS (Java Programming Language
Instrumentation Services) qui permet à
des outils d’analyse d’ajouter du profiling
uniquement lorsque c’est nécessaire.
L’avantage de cette technique est de se
focaliser uniquement sur les analyses et
de ne pas avoir d’interférences d’outils
de profiling de la JVM. L’instrumentation
peut être générée à l’exécution ou au
chargement de classe. L’exemple suivant
crée une instrumentation qui peut charger
une version modifiée d’une classe à partir
du disque. Pour lancer ce test, exécuter
java -javaagent=myBCI BCITest
:
[1] Jean-Baptiste Onofré, « Jboss » in Linux magazine 60.
final private Semaphore s = new Semaphore(1, true);
int balanceAccount = 1000;
s.acquireUninterruptibility();
// si vous ne voulez pas de bloquage, vous pouvez utiliser
s.acquire() à la place. Ici, tant qu’on obtient pas le lock,
on attend.
try {
// on rentre en section critique, ce block est locké
// et donc protégé
balanceAccount = balanceAccount + 10;
}
finally {
s.release(); // on rend le lock disponible
}
java -Dcom.sun.management.jmxremote.port=5001 -Dcom.sun.
management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.
authenticate=false -jar Java2Demo.jar
import java.lang.management.*;
import java.util.*;
public class MemoryUsage {
public static void main(String args[]) {
List<MemoryPoolMXBean> pools = ManagementFactory.
getMemoryPoolMXBeans();
for(MemoryPoolMXBean p: pools) {
System.out.println(„Memory type = „ + p.getType() + „ /
Memory usage = „ + p.getUsage());
}
}
}
Amélioration des diagnostics
Lorsqu’une exception survenait, le code
classique consistait à faire un affichage de
la pile pour remonter à l’origine de l’erreur
(avec la méthode
getStackTrace()
). Mais,
lorsqu’on ne met pas en place d’API
de logging et qu’on a plus de console
d’ouverte, il est parfois difficile de
récupérer ces traces. Java 1.5 a introduit
deux nouvelles méthodes :
getStackTrace
et
Thread.getAllStackTraces
permettent de
récupérer ces traces grâce à du code :
Désormais la JVM inclut un handler
d’erreur qui peut être lancé lorsque la
JVM s’arrête de manière non conforme
(avec l’option
-XX:OnError=
).
Par exemple, vous pouvez envoyer un
mail lorsque la JVM s’arrête ou lancer
gdb
(
%p
représente le processus ID ) :
Client desktop
La première chose que l’on remarque
lorsqu’on lance une application graphique
avec Java 1.5, c’est la rapidité de
chargement.
De nombreuses améliorations de
performances ont été faites au niveau
des API graphiques. Désormais, le toolkit
Swing propose un nouveau thème appelé
« Ocean » et supporte en natif les thèmes
GTK et Windows XP.
Sur Linux, Solaris et Windows, on dispose
de l’accélération OpenGL native (si la
carte vidéo le supporte) en utilisant une
propriété de lancement :
Autre innovation de taille, désormais le
toolkit AWT de Java (celui utilisé par
défaut et par toutes les API graphiques)
est basé sur X11 (et non plus Motif) et de
plus, AWT supporte le protocole XDnD de
X11, ce qui vous permet de faire du drag
and drop avec d’autres applications X11
comme OpenOffice ou Firefox.
Autres nouveautés
Java 1.5 s’est mis à la page concernant le
support du XML avec notamment :
Support de XML 1.1 avec les
namespaces.
Support des schémas XML.
Su
pport de SAX 2.0.2 et DOM level 3.
Nouveau compilateur XSL plus
performant.
De nouveaux caractères ont été
également ajoutés en vue du support de
Unicode 4.0.
Au niveau JDBC, cinq nouvelles classes de
RowSet ont été implémentées. Les deux
plus intéressantes sont CachedRowSet et
WebRowSet.
Les objets de type RowSet, à l’inverse
des objets de type ResultSet, peuvent
manipuler les données sans être
obligatoirement connectés à la base
de données (ou à une autre source de
données).
Ainsi, l’utilisation des RowSet est moins
gourmande en ressources puisqu’on ne
tient pas la connexion à la base.
Ils sont donc plus performants que
les « classiques » ResultSet. Un
CachedRowSet stocke les collections de
lignes en mémoire, et si nécessaire, il
peut être synchronisé avec la base.
D’un autre côté, un WebRowSet stocke les
collections de lignes au format XML. Voilà
un exemple utilisant un WebRowSet :
Conclusion
Java 1.5 est une version majeure de
Java. Il n’y a pas vraiment de nouveaux
concepts révolutionnaires mais beaucoup
de nouveautés simplifiant la vie du
développeur.
De plus, les performances sont au rendez-
vous. Les développeurs ne s’y sont pas
trompés puisque, par exemple, JBoss 4
est développé avec Java 1.5 ainsi que
Apache Geronimo 1.0M3.
15
News
Les nouveautés de Java 1.5 Tiger
Références
http://www.Java Sun.net.
http://java.sun.com/j2se/1.5.0/download.jsp
// fichier myBCI.java
import java.lang.instrument.Instrumentation;
public class myBCI {
private static Instrumentation copy;
public static void premain(String options, Instrumentation
instrumentation) {
copy = instrumentation;
}
public static Instrumentation getInstrumentation() {
return copy;
}
}
// fichier BCITest.java
import java.nio.*;
import java.io.*;
import java.nio.channels.*;
import java.lang.instrument.*;
public class BCITest {
public static void main(String args[]) {
try {
OriginalClass mc = new OriginalClass();
mc.message();
FileChannel fc = new FileInputStream(new
File(„modified“+File.separator+“OriginalClass.class“)).
getChannel();
ByteBuffer buf = fc.map(FileChannel.MapMode.REAL_ONLY,
0, (int)fc.size());
byte[] classBuffer = new byte[buf.capacity()];
buf.get(classBuffer, 0, classBuffer.length);
myBCI.getInstrumentation().redefineClasses(new
ClassDefinition[] { new ClassDefinition(mc.getClass(),
classBuffer) } );
mc.message();
}
catch(Exception e) {}
}
}
// fichier OriginalClass.java
// la version d’origine est compilé dans le répertoire courant
// Copier la source dans un répertoire „modified“, modifier le
message et recompilez
// la classe sera rechargé dynamiquement :)
public class OriginalClass {
public void message() {
System.out.println(“OriginalClass”);
}
}
StackTraceElement e[] = Thread.currentThread().
getStackTrace();
for(int i = 0; i < e.length; i++) {
System.out.println(e[i]);
}
System.out.println(„\n“+Thread.getAllStackTraces());
java -XX:OnError=“mail -s JVMERROR [email protected] ERROR“
java -XX:OnError=“gdb %p“
java -Dsun.java2d.opengl=true -jar Java2D.jar Class.forName(„org.postgresql.Driver“);
WebRowSetImpl wrs = new WebRowSetImpl();
wrs.setCommand(„select username from users“);
wrs.setUsername(“postgres”);
wrs.setPassword(“postgres”);
wrs.setUrl(“jdbc:postgresql://localhost/dbname”);
wrs.execute(); // exécute la requête et stocke le résultat
dans le RowSet
wrs.absolute(1); // retourne le pointeur au début du RowSet
wrs.writeXml(System.out); // export le RowSet sous forme XML
wrs.close();
1 / 5 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !