Tous ceux qui ont rencontrés ce problème pour la première fois ont certainement dû s’arracher les cheveux. Pourquoi donc ce processus Java se plaint-il de ne plus avoir de mémoire alors qu’il n’utilise pas la moitié de ce qui lui est alloué ?

La première partie de la réponse est assez simple… quand on l’a déjà vu! La JVM de Sun définit la taille de la mémoire allouée en deux lots distincts.

  1. La mémoire classique (« heap ») configurée classiquement avec les options -Xms128m et -Xmx256m, respectivement pour la initiale et la taille maxime

  2. La mémoire de la « permanent generation », contenant notamment les déclarations des objets Class (mais pas les instances!) et Method. La taille de cet espace est définit par les options -XX:PermSize=96m et -XX:MaxPermSize=128m, respectivement pour la taille initiale et la taille maximale

Il est tout à fait possible que le réglage par défaut (64Mo de taille maximale) ne suffise pas et qu’une « OutOfMemoryError : PermGen space » apparaisse après quelques minutes d’utilisation de l’application, suite à la compilation d’un volume trop important de JSP. Dans ce cas, augmenter l’espace « permanent generation » à 128Mo devrait résoudre le problème. Attention cependant, comme toutes les options commençant par XX, il s’agit de paramètres spécifiques à l’implémentation de la JVM, en l’occurrence celle de Sun. Ainsi la JVM BEA par exemple ne sépare pas la définition de ces deux espaces dans ses options de JVM.

Donc, grâce à ces options nous voilà débarrassés de cette erreur de mémoire. Pas forcément…

En effet, il est possible que cette erreur réapparaisse par exemple après plusieurs re-déploiements d’une application web sous Tomcat. Dans ce cas, le réglage de la mémoire n’est pas en cause, mais il s’agit bel et bien d’une fuite mémoire. Plus précisément, les classes de l’application que l’on a déchargée ne sont pas recyclées par la JVM. En effet, tant qu’une référence subsiste vers une classe chargée par le classloader de l’application web, ce classloader et toutes les classes qu’il a définit ne pourront pas être recyclés.

Une multitude de causes peuvent aboutir à ce problème, parmi les plus classiques :

  • le chargement d’un driver JDBC dans le classloader d’une application web : le driver (et donc le classloader et toutes ses classes) reste référencé au niveau serveur par le DriverManager, on peut utiliser un ServletContextListener pour décharger le driver

  • une bibliothèque chargée au niveau serveur (type Hibernate) référence dans un cache des classes de l’application (comme par exemple des classes Proxy des classes du modèle)

  • l’application web a fixé des données dans un objet ThreadLocal, liées à un thread du serveur (le thread appartient à un pool du conteneur et n’est jamais recyclé)

Pour plus d’informations sur ce sujet et en particulier une liste d’outils permettant d’identifier la source du problème, je vous conseille cet article.

Pour tester des web services, il n’existe pas énormément de solutions open-source. Je vous en propose 2 en fonction du type de tests que vous souhaitez réaliser.
Apache JMeter est l’outil open-source de tests connu et reconnu. Il est généralement utilisé pour tester les performances et la montée en charge de pages web. Il permet également de tester des bases de données, des serveurs FTP, et bien d’autres ressources. Et, depuis peu, il propose un sampler SOAP (encore en version béta) permettant de simuler des clients (threads) interrogeant un WebService.
Au niveau facilité d’utilisation, il y a encore des efforts à faire. Aucune aide n’est proposée pour générer le message SOAP. Il faut donc écrire (ou générer avec un autre outil) le message dans la zone de texte. Il est également possible de fournir un fichier texte contenant une liste de message SOAP à utiliser pour le test. Pour ceux qui veulent tester des web services compatibles MTOM, oubliez. La version actuelle du sampler ne supporte pas très bien. Il vous dira que votre réponse est invalide et n’affichera que l’entête. Cela suffit pour des tests de charge mais pas pour des tests fonctionnels. Ajoutez un sniffer TCP si vous voulez voir le message compatible MTOM reçu.
Eviware soapUI est moins connu mais spécialisé dans le test des web services. Il propose quelques fonctionnalités dans la version open-source qui dépasse un peu l’objectif du produit, parmi lesquelles on trouve la génération de code pour Axis 1 et 2, xFire et même pour le très récent CXF d’Apache. Très facile d’utilisation, il s’impose comme le couteau-suisse des WS-addicts.
Il n’a, à mon avis, qu’un défaut : il n’est pas (encore) capable de répartir les clients de tests sur plusieurs machines, ce que fait très bien JMeter. Ce n’est pas trop grave pour des tests fonctionnels, mais dès qu’on veut exécuter des tests de charge avec un nombre conséquent de clients (threads) simultanés et que la machine sur laquelle s’exécute l’outil de tests n’est pas à la hauteur, on se rend compte de l’importance de cette possibilité offerte par JMeter.
En conclusion, par son ergonomie et les fonctionnalités offertes, soapUI reste le leader incontestable du test de web services en open-source. Par contre, pour les gros tests de charge (nombre élevé de threads), quand la machine cliente atteint ses limites et risque de fausser les résultats, il faudra préférer JMeter.

Ceux qui ont déjà exécuté des tests de charge, savent que la machine cliente (celle qui simule les utilisateurs) est aussi importante que le serveur testé. Si la machine cliente est incapable de simuler correctement le nombre d’utilisateurs voulu à cause d’un processeur trop faible, d’un manque de mémoire vive, d’un disque dur trop lent, le serveur ne sera pas suffisament stressé et les résultats seront faussés.
Une première solution serait donc d’avoir une machine sur-dimensionnée dédiée uniquement aux tests de charge. Reste que dimensionner correctement une telle machine peut s’avérer difficile et est dépendante de l’outil de tests utilisé et du mode d’utilisation (interface graphique ou ligne de commande). C’est d’autant plus vrai lors des tests de charge aux limites où les demandes en ressources (CPU, RAM, HD, …) seront de plus en plus importante. Si la machine de tests craque avant le serveur, il ne reste plus qu’à investir dans du nouveau matériel.
Apache JMeter propose une alternative : le déclenchement de tests à distance. Il s’agit de mutualiser les ressources de plusieurs machines d’un même réseau pour exécuter un test JMeter. Le déclenchement se fait de façon synchronisée depuis une des machines, soit via l’interface graphique de JMeter, soit par ligne de commande.
Concrètement, l’opération se fait en 3 étapes :
1. Démarrage de serveurs RMI JMeter sur chaque machine “esclave”
2. Enregistrement des noms réseaux (ou adresses IP) sur la machine “maître”
3. Déclenchement du test depuis la machine “maître” (interface graphique ou ligne de commande)
Note 1 : La machine “maître” peut également être “esclave”.
Note 2 : Attention aux firewalls entre les machines du réseau. Le port RMI par défaut (1099) peut être modifié.

Conclusion : Quand vous n’avez à votre disposition que des machines moyennes pour stresser un super-serveur, pensez à mutualiser leurs ressources avant d’envisager l’achat d’une nouvelle machine.

Pour les détails sur ce sujet, jetez un oeil sur le manuel utilisateur de JMeter.

Nombreux sont les developpeurs qui sont encore confrontés à struts aujourd’hui en 2008, un peu moins de 8 ans après sa sortie! C’est une solution éprouvée qui apparait sans risques vue sa grande maturité et qui reste donc très implantée dans beacoup d’entreprises.

Les alternatives ne manquent pourtant pas avec l’émergence de nombreux frameworks tels que stripes, wicket, GWT, grails et j’en passe.

Aujourd’hui je vous présente stripes avec lequel j’ai eu l’occasion de travailler au cours de ma dernière mission.Commencons par le début, la mise en place. Stripes nécessite un filter et une servlet pour fonctionner. Il faut donc les configurer de manière classique dans le web.xml de sa webapp. Un exemple d’une telle configuration se trouve ici : http://www.stripesframework.org/display/stripes/Quick+Start+Guide. Ensuite ajoutez les jars stripes.jar, commons-logging.jar, log4j.jar et cos.jar puis mettez le fichier StripesResources.properties dans WEB-INF/classes et vous êtes parti. A partir de maintenant, la partie configuration se réduit au minimum puisque stripes ne contient aucun fichier xml de configuration!Et c’est là le grand point fort de stripes, tout est fait en annotations java 5. On a donc de manière très simple des jsps, des actionBeans et c’est tout. Pas de struts.xml, pas de validation.xml pas d’actionForms. En clair, moins d’artifacts donc moins d’erreurs.

Comment se fait le binding entre une url et une action me direz vous? En ne faisant rien :)

Stripes utilise le principe de “convention over configuration” sur ce point, et c’est donc le nom de votre actionBean qui determine le nom de votre action. Par exemple un action bean qui s’appelle fr.ippon.stripes.demo.TestActionBean sera accessible sur /demo/Test.action. Bien entendu il est quand même possible d’annoter votre classe pour donner une url spécifique au cas ou celle par défaut ne convient pas.

La relation entre les jsp et votre actionBean ne nécessite pas d’objet supplémentaire type ActionForm struts. En effet, stripes propose sa taglib html qui ira remplir les properties de l’actionBean automatiquement et fera les conversions de type qui vont bien. Les actions n’en deviennent que plus claires : on manipule les champs de la classe directement et il n’y a pas de cast de formulaire, de request.getParameter(“…”).

Autre chose très agréable, stripes instantie pour vous toutes les properties imbriquées nécessaires. Ainsi quelquechose comme <stripes:text name=”user.contact.street”/> instanciera un objet contact dans l’object user de l’actionBean si c’est nécessaire pour pouvoir remplir le champ ‘street’.

Les listes et les maps sont gérées de manières intuitives et efficaces. Déclarez une property private List<Person> persons; dans votre actionBean puis ecrivez tout simplement une boucle <c:foreach dans la jsp et stripes s’occupera d’instancier la liste, d’instancier l’objet de la liste (Person ici) et de remplir les champs, toujours avec les conversions de type qui vont bien.

En terme de validation, stripes passe par des annotations également. Ajoutez @Required sur un champ et il devient obligatoire dans votre formulaire. D’autres validation sont bien sur présentes de base. Concernant les validations de type, le simple fait de dire qu’une property est un integer force l’utilisateur à rentrer un int. Donc la encore, des solutions simples qui peuvent facilement être étendus.

Autre point agréable. Comment transmettre des listes de valeurs à afficher dans des select box avec struts? Passer par une action avant qui prépare la liste et la met en request puis la récuperer de l’autre coté. Pour stripes faire tout ca représente trop de travail. Dans ce cas il suffit juste d’appeler la jsp directement, de placer le tag <stripes:useActionBean bean/> et d’avoir un getter intelligent dans l’action. Le tag instancie alors l’actionBean et le getter doit juste renvoyer une liste qu’on passe en paramètre d’un tag <stripes:options>. Sympathique non?

Bien sûr il y a des tonnes d’autres petites choses qui facilitent la vie du développeur et réduise les erreurs et le temps de developpement d’une manière considérable. Parmi elle, l’intégration spring de base qui permet d’injecter ses services dans ses actionBean sans avoir à rajouter de plugins ou de réinventer une solution à chaque fois, le support d’ajax dans les actions grâce au StreamingResolution qui permet de renvoyer un bout de html par exemple.

Le but de ce post n’est pas de faire une liste exhaustive de tous ces petits trucs mais juste de vous mettre l’eau à la bouche pour que vous alliez voir par vous même.

En terme de points négatifs, pas grand chose à signaler. Il faut quand même avouer que même si la documentation fournie par stripes est très bien faite et complète, on ne trouve pas grand chose ailleurs. Les best practices ne sont pas évidentes à prendre en main puisque personne ne parle vraiment de ce framework… Il manque aussi de la validation coté client.

Bon assez parlé, allez jeter un coup d’oeil. Pour quelqu’un qui connait struts, prendre stripes en main n’est qu’une question d’heures donc pas d’excuse. Au boulot messieurs.

Le 15 janvier se tenait, au CNIT de Paris La Défense, l’événement annuel le plus important de BEA Systems France.
BEA, Emmanuel et Geoffray
Le Convergence Day 2008 a été l’occasion, pour l’éditeur, de donner rendez-vous à ses principaux clients et partenaires, et de présenter ses nouveaux concepts.Cette année, on ne parle plus d’entreprises “Agiles” mais d’entreprise “Fluides” ! C’est la capacité qu’a une entreprise à adapter rapidement son système d’information aux besoins de ses clients. Ce concept porte le nom de “Genesis” chez BEA. Tous ses futurs produits intégreront des fonctionnalités permettant la mise en oeuvre de ce concept.
Après la présentation officielle, durant laquelle est intervenu M. Alfred Chuang, le patron de BEA, la journée s’est poursuivie par de nombreux ateliers animés par des partenaires.Nombre de sites spécialisés ont déjà rapporté la présentation du portail Web “Genesis” ou le retour d’expérience de MM. Bernard Hélie et Yannick Larose respectivement DG du GIP MDS (Groupement d’Intérêt Public Modernisation des Déclarations Sociales) et Senior IT Manager d’Amadeus.
Pour ma part, je retiens la présentation des ateliers “BEA Weblogic Server VirtualEdition” et “CA-Wily Introscope” :
“BEA Weblogic Server VirtualEdition: infrastructure Orientée Services avec la virtualisation”
BEA propose deux modes de virtualisation de ses serveurs :

  • Un premier mode classique dans lequel Weblogic Server est exécuté sur un OS installé sur un environnement virtuel,
  • Un second mode qui met en oeuvre VMware ESX Server (l’hyperviseur de VMWare) et Weblogic Server Virtual Edition (WLSVE).

Parallèlement à la ligne de produits basés sur le serveur Weblogic Serveur 10, BEA propose également une ligne de produits basés sur la version virtualisée de son serveur : Weblogic Server 9.2 Virtual Edition. Pourquoi virtualiser un serveur d’application ?

  • pour utiliser au mieux les ressources des serveurs physiques,
  • pour permettre le transfert d’un serveur applicatif d’un serveur physique à un autre,
  • pour versionner des environnements.

WLSVE intégre une JVM, appelée BEA Liquid VM, s’exécutant directement sur VMware ESX Server. Pour réaliser Liquid VM, BEA a ajouté à sa JVM JRockit 600 fonctions bas niveau prenant en charge la gestion de la mémoire, la gestion des entrées/sorties, la gestion des threads. Liquid VM intégre un serveur SSH/SCP et un “mini” shell. WLSVE pourrait être disponible pour l’hyperviseur Open Source Xen en fin d’année 2008 si un nombre suffisant de clients se déclarent intéressés.Pour administrer les instances de Liquid VM, BEA a développé l’outil “BEA Liquid Operations Control”. Celui-ci permet d’allouer automatiquement des ressources pour les nouveaux systèmes virtuels, et d’installer de nouvelles instances de Liquid VM. Il permet de :

  • déplacer une instance de WLSVE d’un serveur physique chargé à un autre plus disponible,
  • déployer de nouvelles instances de WSVE pour augmenter la capacité d’un cluster Weblogic si le nombre d’utilisateurs connectés à une application dépasse un seuil, par exemple.

Chose intéressante : lorsqu’une instance de WLSVE est arrêtée, les licences qu’elle utilisait redeviennent disponibles.Il est annoncé que BEA LiquidVM soit disponible seul (sans Webogic Server).
“CA-Wily Gestion des applications critique dans les environnements BEA”
Introscope est la solution de gestion et d’optimisation des performances des applications Web critiques, portails et SOA de CA Wily. Comme PerformaSure de Quest Software, des agents, déployés sur vos serveurs, collectent et remontent leurs mesures vers un composant central. Une application d’administration permet d’agréger les informations et d’afficher des métriques.Introscope collecte les données des agents et les mets à disposition des applications d’administration en temps réel. L’utilisation d’Introscope sur des environnements de production engendre une surcharge d’utilisation des processeurs de 3 à 5%. Les données remontées par les agents sont stockées dans un référentiel dont la taille croit, en moyenne, de 1 Go par an. Ces caractéristiques permettent d’installer Introscope sur des environnements de production et sur de longues périodes. En cas d’incident, il est possible de retrouver les différentes métriques et de les contrôler.http://www.wilytech.com/solutions/products/Introscope.html
Rendez-vous l’année prochaine pour Oracle-BEA Convergence Day 2009 !

S’il est un outil que tout développeur Java se doit d’avoir au coin de son disque dur, c’est bien un décompiler Java. Pendant de nombreuses années, Jad a été la référence incontournable dans ce domaine. Malheureusement, ce projet est sérieusement délaissé par son détenteur et les nouveautés de Java 5 n’était plus supportées…C’est ce qui a poussé Emmanuel a s’investir dans ce projet de décompiler Java maison. L’aboutissement de son travail est disponible ici. Je vous invite à l’essayer dès que possible !Merci pour ce travail important généreusement offert à toute la communauté Java. Il ne me reste plus qu’à attendre la version OSX… 😉