tag:linuxfr.org,2005:/sections/javaLinuxFr.org : les dépêches de Java2025-06-16T09:00:23+02:00/favicon.pngtag:linuxfr.org,2005:News/425672025-06-15T09:19:21+02:002025-06-16T09:00:23+02:00Sortie de Datafari 6.2, moteur de recherche open source pour entreprise avec de l'IALicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Nous (NdM: France Labs qui porte datafari.com) sommes fiers de vous annoncer la mise à disposition de Datafari 6.2</p>
<p>Pour faire court, la grosse nouveauté vient de l’intégration simplifiée des outils tiers d’IA générative. Ces travaux ont été en partis financés par le projet Européen NGI Search Neural Datafari, qui a permi du coup également d'ajouter la recherche vectorielle bout en bout au projet Apache Solr.</p>
<p>Pour rappel, Datafari est une solution de recherche pour entreprise. Où que les connaissances se trouvent et sous quelque format que ce soit, elle permet aux employés de retrouver les données utiles. </p>
<p>Et désormais grâce à l’IA, de « discuter » avec ses connaissances. Plus concrètement, il s’agit de récupérer et d’indexer les données et documents depuis de nombreuses sources différentes et plusieurs formats de fichiers, et de permettre aussi de chercher des documents mais aussi d’utiliser une IA générative pour les questionner. </p>
<p>Pour cette dépêche, on se concentre sur la version libre et open source (mais il y a aussi d’autres nouveautés sur la version entreprise propriétaire).</p>
</div><ul><li>lien nᵒ 1 : <a title="https://www.datafari.com/telechargement.html" hreflang="fr" href="https://linuxfr.org/redirect/115830">Page de téléchargement</a></li><li>lien nᵒ 2 : <a title="https://github.com/francelabs/datafari" hreflang="en" href="https://linuxfr.org/redirect/115831">Accéder au code source</a></li><li>lien nᵒ 3 : <a title="https://github.com/francelabs/datafari/discussions" hreflang="en" href="https://linuxfr.org/redirect/115832">Le forum de discussion</a></li><li>lien nᵒ 4 : <a title="https://datafari.atlassian.net/wiki/spaces/DATAFARI/pages/1081354/Introduction" hreflang="en" href="https://linuxfr.org/redirect/115833">La documentation</a></li><li>lien nᵒ 5 : <a title="https://www.datafari.com/" hreflang="fr" href="https://linuxfr.org/redirect/115834">Le site officiel</a></li><li>lien nᵒ 6 : <a title="https://hub.docker.com/r/datafari/datafari" hreflang="en" href="https://linuxfr.org/redirect/115835">Image Docker</a></li><li>lien nᵒ 7 : <a title="https://linuxfr.org/news/sortie-de-datafari-5-3-moteur-de-recherche-open-source-pour-entreprise" hreflang="fr" href="https://linuxfr.org/redirect/115836">La précédente dépêche sur Datafari</a></li></ul><div><p><img src="//img.linuxfr.org/img/68747470733a2f2f7777772e64617461666172692e636f6d2f66696c65732f6461746166617269365f322e6a7067/datafari6_2.jpg" alt="Titre de l'image" title="Source : https://www.datafari.com/files/datafari6_2.jpg"></p>
<p>Notre dernière dépêche datant de… Datafari 5.3, voici Les nouveautés et changements principaux par rapport à cette dernière:</p>
<ol>
<li>Ajout d’un module RAG (Retrieval Augmented Generation)</li>
<li>Passage à Solr 9.8 avec recherche vectorielle</li>
<li>Ajout d’un module d’appel de LLM à l’indexation</li>
<li>Gestion automatique du chunking des documents indexés</li>
<li>Création d’un module autonome d’analytics au lieu de Zeppelin pour optimiser les ressources</li>
<li>Création d’un regex connector à l’indexation</li>
<li>Refonte technique de l’interface graphique, en React</li>
<li>Passage à la V2 des API REST de Datafari</li>
<li>Prototype d’agent autonome pour héberger en local un modèle d’IA</li>
<li>Du bugfix de partout</li>
</ol>
<h3 id="toc-comment-démarrer">Comment démarrer ?</h3>
<p>Pour voir à quoi ça ressemble, nous avons téléversé une courte vidéo de démonstration. Pour démarrer tout de suite, le mieux est d’aller lire le quick start guide. Nous mettons gratuitement à disposition notre documentation Datafari sur Confluence, qui couvre les usages, l’administration et le développement. Attention, les modules d’IA que nous avons développés, nécessitent la disponibilité d’un serveur exposant un modèle d’IA compatible. De base, Datafari n’héberge pas localement une IA. Le plus simple pour débuter est de le connecter par exemple à openAI pour se faire la main, et ensuite de passer à des modèles locaux hébergés par vos soins ou par des partenaires.</p>
<p>Pour rappel, voici les principales fonctionnalités de Datafari en tant que moteur de recherche :</p>
<h3 id="toc-que-peuton-faire-avec-datafari">Que peut‐on faire avec Datafari ?</h3>
<p>Datafari est un moteur de recherche pour entreprise enrichi à l’IA : membres de la famille des outils de gestion des connaissances, les solutions de recherche fédèrent les connaissances en analysant et indexant tous les documents d’une organisation, aussi bien leur contenu que leurs métadonnées. Pour cela, le moteur de recherche doit être multi‐sources, multi‐formats, et gérer la sécurité. En outre, il faut permettre l’administration de l’outil. </p>
<h4 id="toc-dans-la-version-libre-on-peut-côté-admin-">Dans la version libre, on peut, côté admin :</h4>
<ol>
<li>Administrer les connecteurs aux sources de données vers de nombreuses sources (nous utilisons Apache ManifoldCF avec tous ses connecteurs) dont Sharepoint, Confluence, Alfresco et les partages de fichiers ;</li>
<li>Gérer l’algorithme de pertinence qui classe les documents pour leur affichage suite à une requête ;</li>
<li>Activer les modules de recherche vectorielle et de RAG</li>
<li>Mettre en avant des documents pour des requêtes identifiées ;</li>
<li>Créer des utilisateurs et leur assigner des rôles ;</li>
<li>Voir des statistiques d’usage de l’outil ;</li>
<li>Créer l’équivalent de Google AdWords (appelés promoliens) ;</li>
<li>Gérer des synonymes ;</li>
<li>Plein d’autres choses accessibles depuis la documentation Confluence.</li>
</ol>
<h4 id="toc-côté-utilisateur-on-peut-">Côté utilisateur, on peut :</h4>
<ol>
<li>Chercher de façon simple ou avancée ;</li>
<li>Prévisualiser les résultats ;</li>
<li>« Discuter » avec ses documents via le module RAG</li>
<li>Bénéficier de la correction orthographique et de l’auto‐complétion ;</li>
<li>Choisir et utiliser des facettes pour filtrer les résultats ;</li>
<li>Mettre des résultats dans un panier de favoris ;</li>
<li>Créer des alertes par courriel quand des documents modifiés ou nouveaux correspondent à une requête.</li>
</ol>
<h3 id="toc-et-ensuite">Et ensuite ?</h3>
<p>Pour le reste de 2025, nous allons continuer à ajouter des fonctionnalités se basant sur les IA génératives pour multiplier les possibilités.</p>
<h3 id="toc-des-commentaires">Des commentaires ?</h3>
<p>Nous sommes en permanence à l’écoute des commentaires et suggestions pour faire avancer le produit, alors profitez-en, que ce soit d’un point de vue technique ou fonctionnel, ça nous intéresse. Ha et si vous êtes déjà un utilisateur, n’hésitez pas à en parler sur le web !</p>
</div><div><a href="https://linuxfr.org/news/sortie-de-datafari-6-2-moteur-de-recherche-open-source-pour-entreprise-avec-de-l-ia.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/139440/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-datafari-6-2-moteur-de-recherche-open-source-pour-entreprise-avec-de-l-ia#comments">ouvrir dans le navigateur</a>
</p>
Datafarian00Benoît Sibaudhttps://linuxfr.org/nodes/139440/comments.atomtag:linuxfr.org,2005:News/410432022-06-01T10:03:28+02:002022-06-01T10:03:28+02:00Sortie de Cassandre 6.0.0, un cadriciel pour développer votre propre « trading bot »Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Un automate ou robot de trading est un programme qui va automatiquement placer des ordres d’achats et de ventes sur des marchés de crypto-monnaies sans qu’un humain n’ait à intervenir.</p>
<p><img src="https://img.linuxfr.org/img/68747470733a2f2f67626c6f627363646e2e676974626f6f6b2e636f6d2f6173736574732532462d4d442d4f5258452d7a6653597144527955455a2532462d4d452d5246693552536363773647645670324f2532462d4d452d527a3957423178755677557744515a582532466c6f676f5f776974685f746578745f736d616c6c2e706e673f616c743d6d6564696126746f6b656e3d30313634616162662d326533352d346433632d393333372d363963396663663430313730/assets%2F-MD-ORXE-zfSYqDRyUEZ%2F-ME-RFi5RSccw6GdVp2O%2F-ME-Rz9WB1xuVwUwDQZX%2Flogo_with_text_small.png?alt=media&token=0164aabf-2e35-4d3c-9337-69c9fcf40170" alt="Cassandre"></p>
<p>Cassandre, développé en Java et proposé sous licence GPLv3, se présente comme un starter Spring Boot. Après l’avoir ajouté à votre projet et avoir créé une classe annotée, Cassandre se chargera de fournir automatiquement à votre classe les données du marché, les données sur vos comptes et vos ordres. Il vous permettra aussi de passer de nouveaux ordres et de créer des positions.</p>
<p>Cassandre propose aussi un mode qui permet de simuler le fonctionnement du bot avec des données historiques afin de valider vos stratégies.</p>
<p>Avec cette version 6, voici les principaux changements :<br><br>
- Un site web en français ;<br>
- Passage à Java 17 ;<br>
- Migration de la base de données pour gérer correctement les UID/ID ;<br>
- Nouvelle API GraphQL.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://trading-bot.cassandre.tech/fr/" hreflang="fr" href="https://linuxfr.org/redirect/110543">Site web & documentation</a></li><li>lien nᵒ 2 : <a title="https://github.com/cassandre-tech/cassandre-trading-bot" hreflang="en" href="https://linuxfr.org/redirect/110544">Sources</a></li><li>lien nᵒ 3 : <a title="https://github.com/cassandre-tech/cassandre-trading-bot/releases/tag/6.0.0" hreflang="en" href="https://linuxfr.org/redirect/110545">Version 6.0.0</a></li></ul><div></div><div><a href="https://linuxfr.org/news/sortie-de-cassandre-6-0-0-un-cadriciel-pour-developper-votre-propre-trading-bot.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/127871/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-cassandre-6-0-0-un-cadriciel-pour-developper-votre-propre-trading-bot#comments">ouvrir dans le navigateur</a>
</p>
Stéphane TraumatXavier Teyssierhttps://linuxfr.org/nodes/127871/comments.atomtag:linuxfr.org,2005:News/403232021-02-27T10:13:19+01:002021-02-27T13:07:36+01:00Sortie de Cassandre 4.0.0, un cadriciel pour développer votre propre « trading bot »Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Un automate ou robot (bot) de trading est un programme qui va automatiquement placer des ordres d’achats et de ventes sur des marchés de cryptomonnaie (ou des <a href="https://fr.wikipedia.org/wiki/%C3%89change_de_cryptomonnaies">exchanges</a>, dans notre cas) sans qu’un humain n’ait à intervenir.</p>
<p>Cassandre se présente comme un starter Spring Boot. Après l’avoir ajouté à votre projet et avoir créé une classe annotée, Cassandre va se charger de fournir automatiquement à votre classe les données du marché, les données sur vos comptes et vos ordres. Il vous permettra aussi de passer de nouveaux ordres et de créer des positions.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f67626c6f627363646e2e676974626f6f6b2e636f6d2f6173736574732532462d4d442d4f5258452d7a6653597144527955455a2532462d4d452d5246693552536363773647645670324f2532462d4d452d527a3957423178755677557744515a582532466c6f676f5f776974685f746578745f736d616c6c2e706e673f616c743d6d6564696126746f6b656e3d30313634616162662d326533352d346433632d393333372d363963396663663430313730/assets%2F-MD-ORXE-zfSYqDRyUEZ%2F-ME-RFi5RSccw6GdVp2O%2F-ME-Rz9WB1xuVwUwDQZX%2Flogo_with_text_small.png?alt=media&token=0164aabf-2e35-4d3c-9337-69c9fcf40170" alt="Logo de Cassandre" title="Source : https://gblobscdn.gitbook.com/assets%2F-MD-ORXE-zfSYqDRyUEZ%2F-ME-RFi5RSccw6GdVp2O%2F-ME-Rz9WB1xuVwUwDQZX%2Flogo_with_text_small.png?alt=media&token=0164aabf-2e35-4d3c-9337-69c9fcf40170"></p>
<p>À partir de là, vous pourrez développer votre propre stratégie en utilisant les outils et méthodes de vos choix (analyse technique, apprentissage automatique, apprentissage profond…).</p>
</div><ul><li>lien nᵒ 1 : <a title="https://github.com/cassandre-tech/cassandre-trading-bot" hreflang="en" href="https://linuxfr.org/redirect/107928">Sources</a></li><li>lien nᵒ 2 : <a title="https://trading-bot.cassandre.tech/" hreflang="en" href="https://linuxfr.org/redirect/107929">Documentation</a></li></ul><div><p>Grâce à l’utilisation de XChange, nous prenons en charge de nombreux <em>exchanges</em>.</p>
<p>Dans cette version 4.0.0, nous avons ajouté : </p>
<ul>
<li>utilisation de Liquidbase pour garantir une migration facile des prochaines versions ;</li>
<li>refactoring de la base de données pour y stocker l’ensemble des données (<em>orders</em>, <em>trades</em>, <em>positions</em>, <em>strategies</em>) et utiliser la base plutôt que la mémoire ;</li>
<li>ajout de Lomboz pour réduire le code ;</li>
<li>on peut désormais appeler les créations d’ordres et de positions depuis la stratégie sans passer par les services ;</li>
<li>documentation via Qase de tous les tests unitaires ;</li>
<li>ajout d’un objet CurrencyAmount pour gérer plus facilement (comparaison, ajout…) les montants en cryptomonnaies ;</li>
<li>réduction de la taille mémoire (tourne sans problème avec 512Mo de mémoire vive). </li>
</ul>
</div><div><a href="https://linuxfr.org/news/sortie-de-cassandre-4-0-0-un-cadriciel-pour-developper-votre-propre-trading-bot.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/123394/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-cassandre-4-0-0-un-cadriciel-pour-developper-votre-propre-trading-bot#comments">ouvrir dans le navigateur</a>
</p>
Stéphane TraumatBenoît SibaudYsabeau 🧶https://linuxfr.org/nodes/123394/comments.atomtag:linuxfr.org,2005:News/402972021-02-01T22:21:18+01:002021-02-01T22:21:18+01:00Silverpeas 6.2 est sortie malgré le contexte pandémiqueLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>L'année 2020 marque le début d'une période historique dont on se serait bien passée, celle d'une pandémie mondiale qui a ralenti voir paralysé les activités économiques, sociales et culturelle de nos sociétés dîtes modernes. L'épidémie a aussi forcé des entreprises à outrepasser leur frilosité, voire même certains de leurs a priori, et elles ont fini par mettre leurs équipes en télétravail. Ceci s'est particulièrement ressenti par un gain d'intérêt à Silverpeas qui est une plate-forme collaborative open-source qui facilite justement le travail collaboratif à distance entre les personnes et les équipes.</p>
<p><img src="https://img.linuxfr.org/img/68747470733a2f2f7777772e73696c766572706561732e6f72672f696d616765732f6c6f676f2e706e67/logo.png" alt="logo silverpeas"></p>
<p>Pour rappel et pour faire simple, une plate-forme collaborative est un portail d'applications ou de composants qui propose des fonctionnalités de partage et de structuration de l'information, de la connaissance et des compétences, et de mises en relation des individus et des équipes. Bien sur, Silverpeas, comme pour tout autre outil collaboratif, ne fera pas que d'un coup les personnes ou les organisations collaborent parce que ceci est avant tout un état d'esprit et une façon de travailler. Mais il facilitera à chacun d'entre nous et à nos organisations la collaboration déjà existante et donnera les outils pour l'améliorer et l'étendre ; mais ceci restera toujours à la discrétion des individus.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://www.silverpeas.org" hreflang="en" href="https://linuxfr.org/redirect/107818">Site Web du projet</a></li><li>lien nᵒ 2 : <a title="https://bit.ly/SilverpeasReleaseNote-6-2" hreflang="fr" href="https://linuxfr.org/redirect/107819">Notes de version</a></li><li>lien nᵒ 3 : <a title="https://hub.docker.com/_/silverpeas" hreflang="en" href="https://linuxfr.org/redirect/107820">Image Docker</a></li><li>lien nᵒ 4 : <a title="https://www.silverpeas.org/installation/installationV6.html" hreflang="en" href="https://linuxfr.org/redirect/107821">Page d'installation de Silverpeas 6</a></li></ul><div><p>Silverpeas est une plate-forme open-source (Affero GPL) écrite en Java au sein de laquelle un ou plusieurs espaces et sous-espaces de collaboration peuvent être définis. Ce sont dans ceux-ci que des composants fonctionnels (appelés <em>applications</em> dans Silverpeas) peuvent être activés (en une ou plusieurs instances). Chacun de ces composants évoluent plus ou moins indépendamment les uns des autres mais reposent tous sur un socle commun (appelé Silverpeas Core). La particularité de Silverpeas est d'être clé en main, c'est à dire d'être <em>facilement</em> installable (pour une application de cette envergure) et que tous les composants fonctionnels soient disponibles et facilement activables. Nous pouvons démarrer avec un jeu réduit de fonctionnalités qui répondent aux besoins et, au fur et à mesure de l'évolution de ceux-ci, en activer d'autres.</p>
<p>Silverpeas 6.0 est sortie fin janvier 2018, la version 6.1 en juin 2020, et la nouvelle version 6.2 fin janvier 2020.</p>
<p>Silverpeas 6.2 apporte son lot de corrections de bogues mais aussi des nouvelles fonctionnalités dont :</p>
<ul>
<li>L'édition en ligne dans le navigateur et en simultanée (paramétrable par les éditeurs) de documents via une instance de <a href="https://www.libreoffice.org/download/libreoffice-online/">LibreOffice Online</a> (à mettre en place à côté). Jusqu'à présent l'édition en ligne se faisait par WebDAV via sa suite de bureautique préférée (MS-Office, LibreOffice, …). Cette dernière est bien sur toujours présent. </li>
<li>Restriction de la messagerie instantanée à un ou plusieurs groupes d'utilisateurs : en effet, selon leur topologie, il peut ne pas être pertinent d'activer la messagerie instantanée. Pour rappel, la messagerie instantanée repose sur <a href="https://www.jsxc.org/">JSXC</a> et nécessite derrière un serveur XMPP <a href="https://www.ejabberd.im/">eJabberd</a>.</li>
<li>Désormais il est possible d'affiner les utilisateurs à afficher dans l'annuaire général mais aussi d'y inclure des contacts d'<em>Annuaire de Contacts</em>,</li>
<li>Possibilité d'avoir plusieurs agendas au sein d'une seule instance de l'application <em>Calendrier</em> et dont des agendas distants (synchronisation en lecture seule toutefois).</li>
<li>Dans une application <em>Calendrier</em>, les utilisateurs peuvent s'abonner à un agenda particulier pour y être informé de nouveaux événements ou des changements sur ceux-ci.</li>
<li>Amélioration du workflow de suivi des demandes dans l'application <em>Formulaire en Ligne</em> avec support de la mise en brouillon, de la validation successive, etc.</li>
</ul>
<p>Les notes de version (cf lien) à destination des utilisateurs permettront une exhaustivité d'informations sur les nouveautés et fonctions de cette version 6.2</p>
</div><div><a href="https://linuxfr.org/news/silverpeas-6-2-est-sortie-malgre-le-contexte-pandemique.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/123165/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/silverpeas-6-2-est-sortie-malgre-le-contexte-pandemique#comments">ouvrir dans le navigateur</a>
</p>
Miguel MoquillonBenoît Sibaudpalm123bubar🦥devnewton 🍺https://linuxfr.org/nodes/123165/comments.atomtag:linuxfr.org,2005:News/400252020-09-15T14:47:42+02:002020-10-23T18:27:56+02:00Java 15 est sortiLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Ce 15 septembre 2020 sort Java 15. C’est l’occasion pour cette dépêche de revenir sur les nouveautés entre les blocs de texte et autres ramasse‑miettes. On en profite pour parler de quelques informations autour de Java (les vingt‑cinq ans de la plate‑forme, les nouveaux champions, etc).</p>
</div><ul><li>lien nᵒ 1 : <a title="https://openjdk.java.net/projects/jdk/15/" hreflang="en" href="https://linuxfr.org/redirect/106838">OpenJDK 15</a></li><li>lien nᵒ 2 : <a title="https://quarkus.io/blog/quarkus-1-5-final-released/" hreflang="en" href="https://linuxfr.org/redirect/106839">Quarkus 1.5</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#toc-java15">Java 15</a><ul>
<li>
<a href="#toc-abandons">Abandons</a><ul>
<li>
<a href="#toc-cons%C3%A9quences-des-retraits">Conséquences des retraits</a><ul>
<li><a href="#toc-cas-de-la-prise-en-charge-sparcsolaris">Cas de la prise en charge SPARC/SOLARIS</a></li>
<li><a href="#toc-cas-de-la-gestion-du-json">Cas de la gestion du JSON</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#toc-nouveaut%C3%A9s">Nouveautés</a><ul>
<li>
<a href="#toc-ramassemiettes">Ramasse‑miettes</a><ul>
<li><a href="#toc-shenandoah">Shenandoah</a></li>
<li><a href="#toc-zgc">ZGC</a></li>
</ul>
</li>
<li><a href="#toc-blocs-de-texte">Blocs de texte</a></li>
<li><a href="#toc-classes-cach%C3%A9es">Classes cachées</a></li>
<li><a href="#toc-sous-le-capot">Sous le capot</a></li>
<li><a href="#toc-en-vrac">En vrac</a></li>
</ul>
</li>
<li>
<a href="#toc-avantpremi%C3%A8res">Avant‑premières</a><ul>
<li><a href="#toc-filtrage-par-motif-avec-instanceof">Filtrage par motif avec instanceof</a></li>
<li><a href="#toc-sealed-classes">Sealed classes</a></li>
<li><a href="#toc-records">Records</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#toc-%C3%89cosyst%C3%A8me">Écosystème</a><ul>
<li><a href="#toc-fastjar">fast‑jar</a></li>
<li><a href="#toc-d%C3%A9veloppement-du-jdk">Développement du JDK</a></li>
<li><a href="#toc-java-champions">Java champions</a></li>
<li><a href="#toc-vingtcinq-ans-de-java">Vingt‑cinq ans de Java</a></li>
<li><a href="#toc-adoptopenjdk-devient-adoptium">AdoptOpenJDK devient Adoptium</a></li>
</ul>
</li>
</ul>
<h2 id="toc-java15">Java 15</h2>
<h3 id="toc-abandons">Abandons</h3>
<p>Avec ce nouveau rythme, Java s’autorise à supprimer des parties de la plate‑forme. Pour cette version :</p>
<ul>
<li>le système d’exploitation <a href="https://fr.wikipedia.org/wiki/Solaris_(syst%C3%A8me_d%27exploitation)">Solaris</a> et l’architecture <a href="https://fr.wikipedia.org/wiki/Architecture_SPARC">SPARC</a>, <a href="//linuxfr.org/news/java-14-tombe-le-masque#toc-les-mises-au-placard-et-lesd%C3%A9parts">rendus obsolètes par la dernière version</a>, ne sont plus pris en charge (<a href="https://openjdk.java.net/jeps/381">JEP 381</a>) — cocasse quand on connaît les débuts du langage ;</li>
<li>
<a href="https://fr.wikipedia.org/wiki/Nashorn_(moteur_JavaScript)">Nashorn</a>, le moteur JavaScript inclus dans le JDK, a lui aussi été retiré (<a href="https://openjdk.java.net/jeps/372">JEP 372</a>), il était considéré comme obsolète depuis la version 11 sortie en septembre 2018 ;</li>
<li>ce n’est pas encore une suppression, mais RMI activation (et seulement RMI activation pas tout RMI) est rendu obsolète (<a href="https://openjdk.java.net/jeps/385">JEP 385</a>) ;</li>
<li>
<em>biased locking</em> n’est plus activé par défaut (il faut ajouter l’option <code>-XX:+UseBiasedLocking</code>), elle est du même coup considérée obsolète (<a href="https://openjdk.java.net/jeps/374">JEP 374</a>).</li>
</ul>
<h4 id="toc-conséquences-des-retraits">Conséquences des retraits</h4>
<h5 id="toc-cas-de-la-prise-en-charge-sparcsolaris">Cas de la prise en charge SPARC/SOLARIS</h5>
<p>Le JDK étant plutôt vaste, le retrait de la prise en charge d’une architecture a des conséquences à de très nombreux endroits allant des systèmes de construction, la sécurité, la génération du <em>bytecode</em> ou encore la génération d’<a href="https://fr.wikipedia.org/wiki/Interactions_homme-machine" title="interfaces homme‑machine">IHM</a>. La personne en charge de la JEP a donc fait le tour du propriétaire pour retirer tout ce qui devait l’être, comme on peut le voir sur <a href="https://mail.openjdk.java.net/pipermail/jdk-dev/2020-May/004292.html">la liste de diffusion</a>. Les plus curieux pourront suivre les différents liens pour voir le mode de développement du JDK et les spécificités de chaque domaine. Au final, ce sont plus de 127 000 lignes qui ont été supprimées, ce qui ne représente que moins d’un pourcent du nombre total de lignes de code.</p>
<h5 id="toc-cas-de-la-gestion-du-json">Cas de la gestion du JSON</h5>
<p>Suite à la suppression du Nashorn JavaScript Engine, il est apparu que le JDK utilisait le JavaScript et par conséquent le JSON pour certaines fonctionnalités. Se pose alors la question d’une gestion native du JSON ou de laisser cette compétence à des bibliothèques tierces. Actuellement, rien n’est décidé et il y a deux directions possibles :</p>
<ul>
<li>oui, mais sous quelle forme et quand ?</li>
<li>non pas pour éviter d’avoir quelque chose de mal foutu comme pour le XML ou encore le journalisation et se concentrer sur ce qui fait réellement la plus‑value du JDK.</li>
</ul>
<h3 id="toc-nouveautés">Nouveautés</h3>
<h4 id="toc-ramassemiettes">Ramasse‑miettes</h4>
<p>Deux nouveaux <a href="https://fr.wikipedia.org/wiki/Ramasse-miettes_(informatique)">ramasse‑miettes</a> (<em>garbage collectors</em> — gc) sont disponibles en stable avec cette version :</p>
<h5 id="toc-shenandoah">Shenandoah</h5>
<p>Shenandoah est un ramasse‑miettes qui vise à réduire les temps de pause. Pour atteindre cet objectif, il déplace les objets sans avoir à mettre en pause l’application. Il est aussi capable de mieux paralléliser le déplacement d’objet. Cela ne supprime pas totalement les pauses : elles sont encore nécessaires pour libérer la mémoire. Avec Shenandoah, la vérification des objets en vie et leur déplacement se fait sans pause, mais le nettoyage de la mémoire en réclame une. Comme il fait moins de choses pendant les pauses, elles sont plus courtes. L’activation se fait via l’option <code>-XX:+UseShenandoahGC</code>. Ce changement est décrit dans la <a href="https://openjdk.java.net/jeps/379">JEP 379</a>.</p>
<h5 id="toc-zgc">ZGC</h5>
<p>ZGC se donne pour objectif d’avoir des temps de pause faibles, y compris sur de grands tas (<em>heap</em>) de l’ordre du téraoctet. Pour cela, il est capable de décharger les classes sans arrêter l’exécution. Tous les ramasse‑miettes actuels de Java effectuent du déchargement de classes, mais ils sont obligés de le faire uniquement durant le <em>stop the world</em>. ZGC a travaillé pour pouvoir faire cela en concurrence de l’application. Il semble que cela a eu des effets de bord positifs, notamment le temps de pause n’est dépendant que du nombre de fils d’exécution de l’application. Il s’agit de l’amélioration majeure, mais il y a eu bien d’autres travaux comme le fait de pouvoir rendre de la mémoire au système d’exploitation, la gestion de tas de 8 Mio jusqu’à 16 Tio. Actuellement, seuls Windows, macOS et GNU/Linux sur les architectures x86-64 et AArch64 sont pris en charge. Pour l’activer, c’est l’option <code>-XX:+UseZGC</code>. Ce changement est décrit dans la <a href="https://openjdk.java.net/jeps/377">JEP 377</a>.</p>
<blockquote>
<p><em>C’est très bien mais, du coup, comment choisir entre Shenandoah, ZGC ou rester sur G1 ?</em></p>
</blockquote>
<p>C’est une question bien complexe qui est évidemment très dépendante de l’application cible. Premièrement, G1, malgré le fait qu’il continue d’être amélioré, est très loin derrière ZGC et Shenandoah. Les objectifs de ces derniers sont assez similaires et ils sont tellement efficaces qu’on ne peut pas voir de différence entre eux quand ils sont comparés à G1… De mon avis personnel et de ce que j’en ai lu :</p>
<ul>
<li>ZGC est fait pour être simple, il est moins configurable ;</li>
<li>Shenandoah est plus configurable et il offre des temps de pause plus prédictibles que ZGC.</li>
</ul>
<p>Néanmoins, tout cela peut encore changer d’ici la sortie de Java 17 (en septembre 2021).</p>
<h4 id="toc-blocs-de-texte">Blocs de texte</h4>
<p>Les blocs de texte arrivent enfin en version définitive (<a href="https://openjdk.java.net/jeps/378">JEP 378</a>). Cette fonctionnalité a fait beaucoup parler d’elle depuis son introduction en Java 13. Il est donc maintenant possible de définir des chaînes de caractères multilignes comme ça :</p>
<pre><code class="java"><span class="n">String</span> <span class="n">query</span> <span class="o">=</span> <span class="s">"""</span>
<span class="s"> SELECT "</span><span class="n">EMP_ID</span><span class="s">", "</span><span class="n">LAST_NAME</span><span class="s">" FROM "</span><span class="n">EMPLOYEE_TB</span><span class="s">"</span>
<span class="s"> WHERE "</span><span class="n">CITY</span><span class="s">" = 'INDIANAPOLIS'</span>
<span class="s"> ORDER BY "</span><span class="n">EMP_ID</span><span class="s">", "</span><span class="n">LAST_NAME</span><span class="s">";</span>
<span class="s"> """</span><span class="o">;</span></code></pre>
<h4 id="toc-classes-cachées">Classes cachées</h4>
<p>Cette nouveauté offre la possibilité aux cadriciels de générer des classes pour son propre usage qui ne seront pas accessibles de l’extérieur et ainsi de gérer la tambouille interne sans risque de fuite, notamment en utilisant la réflexion.</p>
<p>Java possède des classes internes, qui ne sont pas directement exposées au niveau de l’API, mais qui restent accessibles par réflexion. Ce n’est pas leur nom peu alléchant <code>Unsafe</code> qui empêche qu’elles soient largement utilisées par tout un tas de logiciels. Un des objectifs des développeurs du JDK est de faire en sorte que cette pratique cesse. Un <a href="https://blogs.oracle.com/javamagazine/the-unsafe-class-unsafe-at-any-speed">article de <em>Java Magazine</em></a> en parle et il y a, bien sûr, la <a href="https://openjdk.java.net/jeps/371">JEP 371</a> qui décrit cette évolution.</p>
<p>C’est donc une étape de plus sur la route de la suppression des classes de <code>sun.misc.Unsafe</code>.</p>
<h4 id="toc-sous-le-capot">Sous le capot</h4>
<ul>
<li>cette version inclut la prise en charge des signatures <a href="https://fr.wikipedia.org/wiki/EdDSA" title="Edwards‑Curve Digital Signature Algorithm">EdDSA</a> (<a href="https://openjdk.java.net/jeps/339">JEP 339</a>) ;</li>
<li>l’API <code>DatagramSocket</code> bénéficie d’une réimplémentation (<a href="https://openjdk.java.net/jeps/373">JEP 373</a>).</li>
</ul>
<h4 id="toc-en-vrac">En vrac</h4>
<ul>
<li>nouvelles méthodes pour obtenir une valeur absolue : <a href="https://bugs.openjdk.java.net/browse/JDK-8241374">JDK‑8241374</a> ;</li>
<li>ajout de Unicode 13 : <a href="https://bugs.openjdk.java.net/browse/JDK-8239383">JDK‑8239383</a> ;</li>
<li>mise à jour à la <a href="http://cldr.unicode.org/index/downloads/cldr-37">version 37 de la base Unicode CLDR</a> pour améliorer l’internationalisation de vos logiciels ;</li>
<li>l’AppCDS gère désormais les lambdas, ce qui permet <a href="https://twitter.com/gunnarmorling/status/1272454820474085377">d’accélérer encore un peu</a> le démarrage de la JVM ;</li>
<li>Les énumérations peuvent désormais contenir 4 103 constantes <a href="https://bugs.openjdk.java.net/browse/JDK-8241798">JDK‑8241798</a> !</li>
</ul>
<h3 id="toc-avantpremières">Avant‑premières</h3>
<p>Les fonctionnalités ci‑dessous sont considérées comme en avant‑première (<em>preview</em>), elles sont sujettes à changement d’une version à l’autre.</p>
<h4 id="toc-filtrage-par-motif-avec-instanceof">Filtrage par motif avec instanceof</h4>
<p>La <a href="https://fr.wikipedia.org/wiki/Filtrage_par_motif">filtrage par motif</a> (<em>pattern matching</em>) sur <code>instanceof</code> (<a href="https://openjdk.java.net/jeps/383">JEP 383</a>) permet de discriminer un objet selon sa classe et de récupérer une référence correctement typée. Un exemple possible serait :</p>
<pre><code class="java"><span class="n">Object</span> <span class="n">myVar</span> <span class="o">=</span> <span class="n">foo</span><span class="o">();</span>
<span class="k">if</span> <span class="o">(</span><span class="n">myVar</span> <span class="k">instanceof</span> <span class="n">String</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<p>Cela n’est pas encore disponible avec l’instruction <code>switch</code>.</p>
<h4 id="toc-sealed-classes">Sealed classes</h4>
<p>Les <em>sealed classes</em> sont des classes dont on contrôle l’héritage. Cela permet d’avoir une connaissance à la compilation de toutes les classes filles de cette dernière. Le premier gain est de pouvoir s’assurer qu’on a géré tous les cas dans un <code>switch</code> qui vérifie le type par <code>instanceof</code>. C’est décrit dans la <a href="https://openjdk.java.net/jeps/360">JEP 360</a>.</p>
<p>L’écriture est assez différente de ce que l’on trouve en Scala. Ce dernier oblige à ce que toutes les classes filles soient décrites dans le même fichier. Java garde la volonté d’avoir (en principe) une seule classe par fichier. Cela s’écrit donc ainsi :</p>
<pre><code class="java"><span class="kn">package</span> <span class="nn">org.linuxfr</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">abstract</span> <span class="n">sealed</span> <span class="kd">class</span> <span class="nc">Contenu</span>
<span class="n">permits</span> <span class="n">org</span><span class="o">.</span><span class="na">linuxfr</span><span class="o">.</span><span class="na">Depeche</span><span class="o">,</span>
<span class="n">org</span><span class="o">.</span><span class="na">linuxfr</span><span class="o">.</span><span class="na">Journal</span><span class="o">,</span>
<span class="n">org</span><span class="o">.</span><span class="na">linuxfr</span><span class="o">.</span><span class="na">Lien</span> <span class="o">{</span>
<span class="c1">// ...</span>
<span class="o">}</span></code></pre>
<p>Il faut voir que cela remet en cause les possibilités d’étendre le code. Ça sert quasi uniquement quand on a besoin de l’<em>exhaustive checking</em> au sein du <em>pattern matching</em>. Pour bien décrire l’intérêt, cela permet d’écrire :</p>
<pre><code class="java"><span class="n">String</span> <span class="nf">foo</span><span class="o">(</span><span class="n">Contenu</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">switch</span><span class="o">(</span><span class="n">c</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">Depeche</span> <span class="n">d</span> <span class="o">-></span> <span class="s">"plouf"</span><span class="o">;</span>
<span class="k">case</span> <span class="n">Journal</span> <span class="n">j</span> <span class="o">-></span> <span class="s">"plif"</span><span class="o">;</span>
<span class="k">case</span> <span class="n">Lien</span> <span class="n">l</span> <span class="o">-></span> <span class="s">"plof"</span><span class="o">;</span>
<span class="o">};</span>
<span class="o">}</span></code></pre>
<p>Sans avoir besoin d’avoir un cas <code>default</code>.</p>
<h4 id="toc-records">Records</h4>
<p>Les <em>records</em> (apparus dans la précédente version de Java) sont des classes immuables qui bénéficient d’une syntaxe succincte. Cette mise à jour assure le bon fonctionnement avec les <em>sealed classes</em> et sur l’usage d’annotations, mais la <a href="https://openjdk.java.net/jeps/384">JEP 384</a> est très complète pour décrire tout leur fonctionnement.</p>
<p>Pour ce qui est du code un <code>Point</code> en deux dimensions se déclarera comme ça :</p>
<pre><code class="java"><span class="n">record</span> <span class="nf">Point</span><span class="o">(</span><span class="kt">int</span> <span class="n">x</span><span class="o">,</span> <span class="kt">int</span> <span class="n">y</span><span class="o">)</span> <span class="o">{}</span></code></pre>
<p>Et elle s’utilise comme n’importe quelle classe. Comme pour le constructeur vide créé par défaut, pour vous ici le langage définit le <code>equals()</code>/<code>hashCode()</code>, les <em>getter</em> (avec un style « <em>builder</em> », dans l’exemple on a <code>x()</code> et <code>y()</code>), le constructeur avec le profil que vous avez défini et une méthode <code>toString()</code>. Comme pour le constructeur par défaut, il est possible de surcharger les implémentations fournies. Cela devrait réduire l’intérêt de <a href="https://projectlombok.org/">lombok</a> ou <a href="https://immutables.github.io/">immutables</a>.</p>
<p>Cette nouvelle itération apporte diverses évolutions plus ou moins discrète :</p>
<ul>
<li>il y a l’interdiction d’utiliser <code>this</code> dans le constructeur canonique, c’est la solution trouvée pour éviter aux développeurs peu attentionnés de faire n’importe quoi ;</li>
<li>une modification tardive fait que les attributs des <em>records</em> deviennent réellement finals et ne peuvent pas être modifiés par réflexion <a href="https://bugs.openjdk.java.net/browse/JDK-8247444">JDK‑8247444</a> ;</li>
<li>la possibilité de créer des <code>records</code> locaux de la même manière que les classes ;</li>
<li>les <a href="https://inside.java/2020/07/20/serializablerecords/">mécanismes de sérialisation et de désérialisation</a> propre et qui, donc, diffèrent des classes :
<ul>
<li>la sérialisation est basée seulement sur l’état de l’objet,</li>
<li>la « désérialisation » utilise uniquement le constructeur canonique.</li>
</ul>
</li>
</ul>
<p>La version finale sera certainement livrée en version 16.</p>
<h2 id="toc-Écosystème">Écosystème</h2>
<h3 id="toc-fastjar">fast‑jar</h3>
<p>Le projet <a href="https://en.wikipedia.org/wiki/Quarkus">Quarkus</a> est un cadriciel Java alternatif à Spring visant l’extrême performance et à être <em>developer friendly</em>. Sa version 1.5 propose un nouvel empaquetage pour les applications Java nommé fast‑jar.</p>
<p>Un fichier au format JAR est une archive ZIP des applications Java contenant les classes compilées ainsi que quelques fichiers de description et des fichiers de configuration de l’application. Il est possible d’y inclure les bibliothèques utilisées par l’application : c’est ce que l’on appelle un fat‑jar ou un uber‑jar. C’est un peu comme une compilation statique, cela permet de distribuer l’application avec un unique fichier (il faut « juste » avoir un JDK installé).</p>
<p>La simplicité de ces uber‑jar leur a fait rencontrer un vif succès, mais l’arrivée de Docker a un peu changé la donne. Le système de couches de Docker (une image Docker dépend d’une précédente image dont on a modifié le contenu) pousse à organiser ses images comme suit :</p>
<ol>
<li>l’image de base contenant le JDK ;</li>
<li>on ajoute les dépendances de l’application dans une couche dédiée ;</li>
<li>on ajoute l’application dans une autre couche ;</li>
<li>si applicable, on ajoute les fichiers de configuration dans une dernière couche.</li>
</ol>
<p>L’idée sous‑jacente est de découper les couches en fonction de la fréquence de mise à jour :</p>
<ol>
<li>on modifie plus fréquemment sa configuration que l’application ;</li>
<li>on met à jour plus fréquemment l’application que ses dépendances ;</li>
<li>on met à jour plus fréquemment les dépendances que le JDK.</li>
</ol>
<p>Cela permet de ne télécharger que les dernières couches lors des mises à jour.</p>
<p>Lors de leurs tests de performance, les développeurs de Quarkus se sont rendu compte que le temps de démarrage d’une application uber‑jar est bien plus court qu’avec les dépendances séparées (<a href="https://twitter.com/agoncal/status/1298205802709364737">voir ici</a>). Pour pouvoir à la fois avoir un empaquetage Java efficace et continuer de suivre les bonnes pratiques Docker, ils ont créé fast‑jar. Il s’agit simplement d’un JAR éclaté, mais qui possède un index dans le JAR principal qui indique où trouver chaque classe. Le chargeur de classes n’a donc plus à aller chercher dans chaque JAR si la classe qu’il cherche s’y trouve ou non.</p>
<h3 id="toc-développement-du-jdk">Développement du JDK</h3>
<p>La version 16 du JDK donnera quelques modifications importantes dans son développement :</p>
<ul>
<li>passage à C++14 (<a href="https://openjdk.java.net/jeps/347">JEP 347</a>) ; actuellement cantonné à C++98, les nouveaux développements seront effectués avec la norme C++14, la JEP décrit ce qui est autorisé ou non d’utiliser ;</li>
<li>
<a href="//linuxfr.org/users/devnewton/liens/l-openjdk-abandonne-mercurial-pour-git"><em>devnewton</em> en avait parlé dans les liens</a> : passage de Mercurial à Git (<a href="https://openjdk.java.net/jeps/357">JEP 357</a>), cette décision est motivée par la taille de l’historique, l’outillage autour de Git et les hébergements disponibles pour Git — justement, dans la foulée, il a été décidé de partir chez GitHub (<a href="https://openjdk.java.net/jeps/369">JEP 369</a>) ; vous trouverez les raisons de ce changement dans la JEP associée : <em><a href="https://openjdk.java.net/jeps/369#Why-GitHub?">Why GitHub?</a></em>
</li>
</ul>
<h3 id="toc-java-champions">Java champions</h3>
<p>Les <em>Java Champions</em> sont un groupe de promoteurs de Java indépendants d’Oracle (ou de Sun à l’époque). Les membres sont élus par leurs pairs (et sont aussi proposés à l’élection de cette façon).</p>
<p>Le 5 mai dernier, Audrey Neveu était élue <em>Java Champion</em>. Elle travaille chez <a href="https://en.wikipedia.org/wiki/Pivotal_Software">Pivotal</a> comme développeuse Java, Kotlinv et JS, et est surtout connue en tant que membre des <em><a href="https://lescastcodeurs.com/">Cast Codeurs</a></em> où elle sensibilise aux enjeux sociétaux que les technologies peuvent poser (les risques liés aux libertés, les problèmes que les GAFAM peuvent induire…).</p>
<h3 id="toc-vingtcinq-ans-de-java">Vingt‑cinq ans de Java</h3>
<p>Le 25 mai dernier Java a soufflé ses vingt‑cinq bougies. Ça a été l’occasion de créer différents évènements : par exemple, Oracle a mis en ligne <em><a href="https://www.oracle.com/java/moved-by-java/">Moved by Java</a></em>, et ParisJUG a organisé une soirée rétrospective avec plusieurs champions Java francophones c’est <a href="https://www.youtube.com/watch?v=ocQeuV8vejw">visible sur YouTube</a>. On y retrouve pêle‑mêle :</p>
<ul>
<li>
<a href="https://twitter.com/audrey_neveu">Audrey Neveu</a>, nouvelle championne ;</li>
<li>
<a href="https://antoniogoncalves.org/">Antonio Gonçalves</a>, cofondateur du ParisJUG, de Devoxx France, il travaille pas mal autour de Java EE ;</li>
<li>
<a href="https://emmanuelbernard.com/">Emmanuel Bernard</a>, développeur Red Hat sur les projets Hibernate et maintenant Quarkus ;</li>
<li>
<a href="https://www.jmdoudoux.fr/">Jean‑Michel Doudoux</a> il a produit énormément de documentations autour de Java, entre autres sur <em><a href="https://jmdoudoux.developpez.com/cours/developpons/java/">Developpez.com</a></em>, il en publie aussi sur son <a href="http://www.jmdoudoux.fr/accueil_java.htm">propre site</a> ;</li>
<li>
<a href="http://www-igm.univ-mlv.fr/%7Eforax/">Rémi Forax</a>, enseignant à l’université, il est contributeur OpenJDK depuis très longtemps.</li>
</ul>
<p>Il y a aussi un article sympa listant <a href="https://blogs.oracle.com/javamagazine/the-top-25-greatest-java-apps-ever-written">25 super‑applications</a>.</p>
<h3 id="toc-adoptopenjdk-devient-adoptium">AdoptOpenJDK devient Adoptium</h3>
<p>AdoptOpenJDK est une distribution de Java très populaire. Elle a rejoint en juin dernier la <a href="https://blog.adoptopenjdk.net/2020/06/adoptopenjdk-to-join-the-eclipse-foundation/">fondation Eclipse</a>. Il peut être compliqué d’un point de vue légal d’utiliser le nom « OpenJDK », il a donc été choisi de renommer le projet <a href="https://projects.eclipse.org/projects/adoptium">Eclipse Adoptium</a>. Cela va permettre au projet de bénéficier de toute l’infrastructure proposée par Eclipse d’un point de vue technique (hébergement par exemple) et organisationnel (la gouvernance n’est pas attachée à une éventuelle entreprise).</p>
</div><div><a href="https://linuxfr.org/news/java-15-est-sorti.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/121494/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/java-15-est-sorti#comments">ouvrir dans le navigateur</a>
</p>
barmicbobble bubbleNonolapéroYves BourguignonLawlessBenoît SibaudBAudDavy DefaudtheojouedubanjoYsabeau 🧶https://linuxfr.org/nodes/121494/comments.atomtag:linuxfr.org,2005:News/397782020-04-09T10:57:57+02:002020-04-09T18:50:41+02:00Sortie de Cassandre, un cadriciel pour développer votre propre « trading bot »Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Un automate ou robot (<em>bot</em>) de <em>trading</em> est un programme qui va automatiquement placer des ordres d’achats et de ventes sur des marchés de cryptomonnaie (ou des <em>Exchanges</em>, dans notre cas) sans qu’un humain n’ait à intervenir. L’avantage est, bien sûr, qu’ils travaillent 24 h / 24 et qu’ils sont toujours concentrés !</p>
<p>Cassandre se présente comme un <em>starter</em> <a href="https://spring.io/projects/spring-boot">Spring Boot</a>. Après l’avoir ajouté à votre projet et avoir créé une classe annotée, Cassandre va se charger de fournir automatiquement à votre classe les données du marché, les données sur vos comptes et vos ordres. Il vous permettra aussi de passer de nouveaux ordres. </p>
<p>À partir de là, vous pourrez développer votre propre stratégie en utilisant les outils et méthodes de vos choix (analyse technique, <a href="https://fr.wikipedia.org/wiki/apprentissage%20automatique" title="Définition Wikipédia">apprentissage automatique</a>, <a href="https://fr.wikipedia.org/wiki/apprentissage%20profond" title="Définition Wikipédia">apprentissage profond</a>…).</p>
<p>Avec ce projet, notre but est de démystifier ce domaine et de partager ce que nous apprenons, vous pourrez donc aussi trouver un guide complet sur le développement du <em>bot</em> et un début de cours sur le développement de stratégie (on a déjà pas mal avancé sur l’analyse technique).</p>
<p>Grâce à l’utilisation de XChange, nous prenons potentiellement en charge de nombreux <em>Exchanges</em>.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://github.com/cassandre-tech/cassandre-trading-bot" hreflang="en" href="https://linuxfr.org/redirect/106041">Sources (GitHub)</a></li><li>lien nᵒ 2 : <a title="https://trading-bot.cassandre.tech/" hreflang="en" href="https://linuxfr.org/redirect/106042">Guide</a></li><li>lien nᵒ 3 : <a title="https://github.com/knowm/XChange" hreflang="en" href="https://linuxfr.org/redirect/106043">XChange</a></li><li>lien nᵒ 4 : <a title="https://spring.io/projects/spring-boot" hreflang="en" href="https://linuxfr.org/redirect/106044">Spring Boot</a></li></ul><div></div><div><a href="https://linuxfr.org/news/sortie-de-cassandre-un-cadriciel-pour-developper-votre-propre-trading-bot.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/119932/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-cassandre-un-cadriciel-pour-developper-votre-propre-trading-bot#comments">ouvrir dans le navigateur</a>
</p>
Stéphane TraumatDavy DefaudBenoît Sibaudhttps://linuxfr.org/nodes/119932/comments.atomtag:linuxfr.org,2005:News/397322020-03-18T14:50:21+01:002020-03-21T03:06:19+01:00Java 14 tombe le masqueLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>À quelques jours du printemps, une nouvelle version de Java arrive avec son lot de corrections, améliorations, nouveautés et retraits. Voilà six mois que <a href="//linuxfr.org/news/sortie-d-openjdk-13">Java 13</a> a apporté ses quelques nouveautés. Cette nouvelle itération est bien plus riche aussi bien sur les fonctionnalités définitives que sur celles en cours de maturation. Au programme pas moins de <a href="https://openjdk.java.net/projects/jdk/14/">16 JEP</a> intègrent le langage. Seulement une partie sera détaillée dans la suite de dépêche.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://openjdk.java.net/projects/jdk/14/" hreflang="en" href="https://linuxfr.org/redirect/105889">Les JEPs OpenJDK 14</a></li><li>lien nᵒ 2 : <a title="https://builds.shipilev.net/backports-monitor/release-notes-14.txt" hreflang="en" href="https://linuxfr.org/redirect/105933">L’ensemble des améliorations et des corrections</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#toc-les-nouveaut%C3%A9s-d%C3%A9finitives">Les nouveautés définitives</a><ul>
<li><a href="#toc-temps-de-d%C3%A9marrage-et-empreintem%C3%A9moire">Temps de démarrage et empreinte mémoire</a></li>
<li>
<a href="#toc-du-c%C3%B4t%C3%A9-des-ramassemiettes">Du côté des ramasse‑miettes</a><ul>
<li><a href="#toc-g1">G1</a></li>
<li><a href="#toc-les-ramassemiettes-exp%C3%A9rimentaux">Les ramasse‑miettes expérimentaux</a></li>
</ul>
</li>
<li><a href="#toc-switch-statement-et-switchexpression">Switch statement et switch expression</a></li>
<li><a href="#toc-jdk-flight-recorder-event-streaming">JDK Flight Recorder Event Streaming</a></li>
<li><a href="#toc-des-nullpointerexception-plusexplicites">Des NullPointerException plus explicites</a></li>
</ul>
</li>
<li>
<a href="#toc-nouveaut%C3%A9s-en-pr%C3%A9visualisation">Nouveautés en prévisualisation</a><ul>
<li><a href="#toc-records">Records</a></li>
<li><a href="#toc-pattern-matching-instanceof">Pattern Matching instanceof</a></li>
<li><a href="#toc-outils-dempaquetage">Outils d’empaquetage</a></li>
<li><a href="#toc-les-blocs-de-texte-secondeit%C3%A9ration">Les blocs de texte, seconde itération</a></li>
</ul>
</li>
<li><a href="#toc-les-mises-au-placard-et-lesd%C3%A9parts">Les mises au placard et les départs</a></li>
<li><a href="#toc-dans-les-prochaines-versions">Dans les prochaines versions</a></li>
</ul>
<h2 id="toc-les-nouveautés-définitives">Les nouveautés définitives</h2>
<p>Avec la nouvelle cadence de versionnage, les nouveautés arrivent plus tôt mais dans un état non définitif et profitent des retours d’expérience des utilisateurs.</p>
<h3 id="toc-temps-de-démarrage-et-empreintemémoire">Temps de démarrage et empreinte mémoire</h3>
<p>Depuis plusieurs versions, les temps de démarrage et l’empreinte mémoire diminuent. Il est possible d’espérer un gain d’une dizaine de pourcents sur le temps de démarrage, c’est toujours ça de pris ! Côté empreinte mémoire, en revanche, la baisse est plus conséquente, de l’ordre de 30 % à 40 %. Ces améliorations sont natives, il n’est pas nécessaire d’ajouter des options. Pour plus de détails, une <a href="//linuxfr.org/users/nonolapero/liens/presentation-sur-l-amelioration-des-performances-de-java-depuis-plusieurs-versions">présentation</a> et un <a href="https://cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.html">article</a>.</p>
<h3 id="toc-du-côté-des-ramassemiettes">Du côté des ramasse‑miettes</h3>
<h4 id="toc-g1">G1</h4>
<p>G1 est le ramasse‑miettes par défaut depuis Java 8 et il progresse de version en version à tous les niveaux (temps de réponse, gestion de la mémoire). Je vous laisse regarder cette <a href="https://fosdem.org/2020/schedule/event/g1/">présentation</a> ou le <a href="http://cr.openjdk.java.net/%7Esjohanss/slides/fosdem_2020_-_g1.pdf">support</a>. Cette progression est une bonne raison pour ne plus rester sur Java 8, car aucune amélioration n’est portée sur les versions antérieures.</p>
<h4 id="toc-les-ramassemiettes-expérimentaux">Les ramasse‑miettes expérimentaux</h4>
<p>ZGC (disponible depuis Java 11) fonctionne sur les trois principaux systèmes d’exploitation et il devrait bientôt ne plus être expérimental si l’on en croit cette <a href="https://openjdk.java.net/jeps/8209683">JEP</a>. L’idée derrière ZGC est de proposer un ramasse‑miettes à faible latence et qui peut aussi bien gérer des petites ou des grosses quantités de mémoire.<br>
Shenandoah est un autre ramasse‑miettes à faible latence intégré depuis Java 12, son objectif est d’avoir des temps de pause identiques quelle que soit la quantité de mémoire à libérer. Si vous voulez savoir comment ça fonctionne et avoir un état d’avancement du projet, je vous laisse regarder cette <a href="https://fosdem.org/2020/schedule/event/shenandoah/">présentation</a> et pour les explications plus détaillées c’est <a href="https://developers.redhat.com/blog/2020/03/04/shenandoah-gc-in-jdk-14-part-1-self-fixing-barriers/">ici (partie 1)</a>, puis <a href="https://developers.redhat.com/blog/2020/03/09/shenandoah-gc-in-jdk-14-part-2-concurrent-roots-and-class-unloading/">là (partie 2)</a>.</p>
<h3 id="toc-switch-statement-et-switchexpression">Switch statement et switch expression</h3>
<p>Les <em>switch expression</em> et <em>switch statement</em> sont arrivées dans la version 12, ont été revues dans la version 13 et sont définitives dans cette version 14 (voir la <a href="https://openjdk.java.net/jeps/361">JEP 361</a>).</p>
<p>Avant, on devait écrire :</p>
<pre><code class="java"><span class="kd">public</span> <span class="kd">enum</span> <span class="n">Event</span> <span class="o">{</span>
<span class="n">PLAY</span><span class="o">,</span> <span class="n">PAUSE</span><span class="o">,</span> <span class="n">STOP</span>
<span class="o">}</span>
<span class="n">String</span> <span class="n">log</span><span class="o">;</span>
<span class="k">switch</span> <span class="o">(</span><span class="n">event</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">PLAY</span><span class="o">:</span>
<span class="n">log</span> <span class="o">=</span> <span class="s">"User has triggered the play button"</span><span class="o">;</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="n">STOP</span><span class="o">:</span>
<span class="k">case</span> <span class="n">PAUSE</span><span class="o">:</span>
<span class="n">log</span> <span class="o">=</span> <span class="s">"User needs a break"</span><span class="o">;</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="n">String</span> <span class="n">message</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span>
<span class="n">LocalDateTime</span> <span class="n">now</span> <span class="o">=</span> <span class="n">LocalDateTime</span><span class="o">.</span><span class="na">now</span><span class="o">();</span>
<span class="n">log</span> <span class="o">=</span> <span class="s">"Unknown event "</span> <span class="o">+</span> <span class="n">message</span> <span class="o">+</span>
<span class="s">" logged on "</span> <span class="o">+</span> <span class="n">now</span><span class="o">;</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span></code></pre>
<p>Et maintenant, cette syntaxe est possible :</p>
<pre><code class="java"><span class="n">var</span> <span class="n">log</span> <span class="o">=</span> <span class="k">switch</span> <span class="o">(</span><span class="n">event</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">PLAY</span> <span class="o">-></span> <span class="s">"User has triggered the play button"</span><span class="o">;</span>
<span class="k">case</span> <span class="n">STOP</span><span class="o">,</span> <span class="n">PAUSE</span> <span class="o">-></span> <span class="s">"User needs a break"</span><span class="o">;</span>
<span class="k">default</span> <span class="o">-></span> <span class="o">{</span>
<span class="n">String</span> <span class="n">message</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span>
<span class="n">LocalDateTime</span> <span class="n">now</span> <span class="o">=</span> <span class="n">LocalDateTime</span><span class="o">.</span><span class="na">now</span><span class="o">();</span>
<span class="n">yield</span> <span class="s">"Unknown event "</span> <span class="o">+</span> <span class="n">message</span> <span class="o">+</span>
<span class="s">" logged on "</span> <span class="o">+</span> <span class="n">now</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">};</span></code></pre>
<p>Avec cette nouvelle forme :</p>
<ul>
<li>il n’y a plus de risque d’oublier un <code>break</code> en cours de chemin ;</li>
<li>il n’est plus nécessaire d’instancier une variable à vide ;</li>
<li>c’est plus court !</li>
</ul>
<p>Autre fait notable, le cas par défaut n’est plus obligatoire lorsque toutes les possibilités d’un <code>enum</code> sont traitées. Par précaution, en rajouter un peut protéger s’il y a un ajout dans l’énumération.</p>
<p>Le mélange des syntaxes est aussi possible avec des risques d’erreurs comme le montre l’exemple suivant :</p>
<pre><code class="java"><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="k">switch</span> <span class="o">(</span><span class="n">day</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">MONDAY</span> <span class="o">-></span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Monday"</span><span class="o">);</span>
<span class="c1">// ERROR! Block doesn't contain a yield statement</span>
<span class="o">}</span>
<span class="k">default</span> <span class="o">-></span> <span class="mi">1</span><span class="o">;</span>
<span class="o">};</span>
<span class="n">i</span> <span class="o">=</span> <span class="k">switch</span> <span class="o">(</span><span class="n">day</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">MONDAY</span><span class="o">,</span> <span class="n">TUESDAY</span><span class="o">,</span> <span class="n">WEDNESDAY</span><span class="o">:</span>
<span class="n">yield</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Second half of the week"</span><span class="o">);</span>
<span class="c1">// ERROR! Group doesn't contain a yield statement</span>
<span class="o">};</span></code></pre>
<p>Chacun se fera son avis sur ces nouvelles formes, car autant un <code>switch case</code> à l’ancienne est pénible à écrire, autant avec les nouvelles possibilités il va falloir s’accorder sur le style à suivre sur un projet. </p>
<h3 id="toc-jdk-flight-recorder-event-streaming">JDK Flight Recorder Event Streaming</h3>
<p>Dans Java 11, Oracle a libéré <a href="https://openjdk.java.net/jeps/328">Flight Recorder</a> (FR) qui permet de suivre l’activité d’une application du sol au plafond, c’est‑à‑dire des appels processeur aux méthodes utilisées pour faire de l’affichage, en passant par le ramasse‑miettes et par le compilateur à la volée. Pour diverses explications, du code et des démos, allez voir cette <a href="https://www.infoq.com/presentations/monitoring-jdk-jfr/">conférence</a> ou encore <a href="https://blogs.oracle.com/javamagazine/java-flight-recorder-and-jfr-event-streaming-in-java-14">cet article</a>. Toutefois, pour découvrir l’outil rapidement, il faut lancer votre application avec <code>java -XX:StartFlightRecording:filename=/tmp/monAppli.jfr -jar monAppli.jar</code>, interagir avec durant quelques instants et l’arrêter. Il est aussi possible de démarrer les enregistrements sur une application déjà en fonctionnement avec <code>jcmd MainClass JFR.start</code>. Ensuite, vous pouvez profiter d’un résumé des évènements enregistrés avec <code>$JAVA_HOME/bin/jfr summary /tmp/monAppli.jfr | less</code> ; pour une analyse plus poussée, <a href="https://adoptopenjdk.net/jmc.html">Java Mission Control</a> est bien plus adapté.<br>
Le JDK Flight Recorder Event Streaming apporte la possibilité de profiter directement de ces mesures sans passer par la case écriture dans un fichier et lecture à partir de ce dernier. Ça peut sembler basique, mais ça ouvre de nombreuses possibilités pour monitorer de façon déportée différents services (un <a href="https://github.com/gunnarmorling/jfr-custom-events">exemple</a> avec du Grafana et du Quarkus).</p>
<h3 id="toc-des-nullpointerexception-plusexplicites">Des NullPointerException plus explicites</h3>
<p>Dorénavant, les développeurs Java auront moins d’excuses pour passer de longs moments à décortiquer les NPE, car elles indiqueront quel objet est <code>null</code>. Cette fonctionnalité existe depuis 2006 dans le JDK de SAP, et la plus grande ouverture des contributions à Java a permis de la rendre disponible au plus grand nombre. Pour Java 14, il faudra activer l’option <code>-XX:+ShowCodeDetailsInExceptionMessages</code> afin d’en profiter et, à partir de Java 15, l’option sera activée par défaut.</p>
<h2 id="toc-nouveautés-en-prévisualisation">Nouveautés en prévisualisation</h2>
<h3 id="toc-records">Records</h3>
<p>La verbosité du langage n’est plus à démontrer et, pour alléger la charge, des efforts sont faits, notamment avec de l’inférence de type avec le mot clé <code>var</code> au moment de déclarer une variable. Les <em>records</em> vont dans ce sens‑là, mais en plus ils permettent de transporter de la donnée de manière immutable. Voici un petit exemple de code :</p>
<pre><code class="java"><span class="kd">public</span> <span class="n">record</span> <span class="nf">Bouchot</span><span class="o">(</span><span class="n">String</span> <span class="n">nom</span><span class="o">){}</span></code></pre>
<p>C’est tout, une seule ligne pour créer un <em>record</em> ! Derrière, le langage se débrouille pour générer les méthodes <code>equals()</code>, <code>toString()</code> et <code>hashCode()</code>. Pour accéder au nom d’un bouchot (que l’on aura déclaré comme ceci : <code>var monBouchot = new Bouchot("DLFP")</code>, il suffit de faire <code>monBouchot.nom()</code>. Un <em>record</em> reste une classe Java, avec quelques limitations toutefois, il est donc possible de rajouter des contraintes sur le constructeur, par exemple refuser les <code>null</code> ou écrire votre propre méthode <code>toString()</code>, si la version générée ne vous convient pas.</p>
<pre><code class="java"><span class="kd">public</span> <span class="n">record</span> <span class="nf">Bouchot</span><span class="o">(</span><span class="n">String</span> <span class="n">nom</span><span class="o">){</span>
<span class="kd">public</span> <span class="n">Bouchot</span> <span class="o">{</span>
<span class="k">if</span><span class="o">(</span><span class="kc">null</span> <span class="o">==</span> <span class="n">nom</span><span class="o">){</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span><span class="s">"Crois‑tu qu’une moule puisse s’accrocher à null ?"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre>
<p>Une chose intéressante à savoir est que les <em>records</em> ont été définis en prenant en compte le futur du langage aussi bien du côté développeur (types scellés, <em>pattern matching</em> et déconstruction) que de la machinerie interne (<em>inline type</em>). Pour aller plus loin, je vous laisse lire cet <a href="https://www.infoq.com/articles/java-14-feature-spotlight/">article</a>.</p>
<h3 id="toc-pattern-matching-instanceof">Pattern Matching instanceof</h3>
<p>Java est le dernier des principaux langages fonctionnant sur la JVM à ne pas implémenter le <em>pattern matching</em>. Pour cette première, il commence modestement en apportant un peu plus de légèreté syntaxique.</p>
<pre><code class="java"><span class="c1">// Avant avec le cast</span>
<span class="k">if</span> <span class="o">(</span><span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Bouchot</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Bouchot</span> <span class="n">b</span> <span class="o">=</span> <span class="o">(</span><span class="n">Bouchot</span><span class="o">)</span> <span class="n">obj</span><span class="o">;</span>
<span class="n">var</span> <span class="n">nom</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="na">nom</span><span class="o">();</span>
<span class="o">}</span>
<span class="c1">//Après</span>
<span class="k">if</span> <span class="o">(</span><span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Bouchot</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
<span class="n">var</span> <span class="n">nom</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="na">nom</span><span class="o">();</span>
<span class="o">}</span></code></pre>
<p>L’étape suivante est de combiner le <em>pattern matching</em> avec les <em>switch expressions</em> et de pouvoir déconstruire les <em>records</em>. Tout le programme est détaillé dans la <a href="https://openjdk.java.net/jeps/375">JEP 375</a> et en voici un avant‑goût :</p>
<pre><code class="java"><span class="n">record</span> <span class="nf">Point</span><span class="o">(</span><span class="kt">int</span> <span class="n">x</span><span class="o">,</span> <span class="kt">int</span> <span class="n">y</span><span class="o">)</span> <span class="o">{}</span>
<span class="k">if</span> <span class="o">(</span><span class="n">obj</span> <span class="k">instanceof</span> <span class="nf">Point</span><span class="o">(</span><span class="n">var</span> <span class="n">a</span><span class="o">,</span> <span class="n">var</span> <span class="n">b</span><span class="o">))</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<h3 id="toc-outils-dempaquetage">Outils d’empaquetage</h3>
<p>L’idéal de Java qui était, si je ne me trompe pas, compile ton application une seule fois et elle fonctionnera partout, semble ne plus trop être à l’ordre du jour. La démarche est plus, livre ton application avec les modules Java strictement nécessaires et, optionnellement, le JRE qui va avec. Le but étant la diminution de la taille des applications mais aussi l’amélioration de la réactivité et de la sécurité, car moins de code sera chargé et donc exposé. Comme d’habitude, les détails sont à lire dans la <a href="https://openjdk.java.net/jeps/343">JEP 343</a>.</p>
<h3 id="toc-les-blocs-de-texte-secondeitération">Les blocs de texte, seconde itération</h3>
<p>Après une première implémentation dans la version précédente de Java, en voici une nouvelle (<a href="https://openjdk.java.net/jeps/368">JEP 368</a>). Le principe est d’avoir une solution élégante pour se débarrasser des concaténations sur plusieurs lignes, de se battre avec les échappements divers et variés et surtout améliorer la lisibilité.</p>
<pre><code class="java"><span class="n">String</span> <span class="n">query</span> <span class="o">=</span> <span class="s">"""</span>
<span class="s"> SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`</span>
<span class="s"> WHERE `CITY` = 'INDIANAPOLIS'</span>
<span class="s"> ORDER BY `EMP_ID`, `LAST_NAME`;</span>
<span class="s"> """</span><span class="o">;</span></code></pre>
<p>C’est aussi utilisable en combinaison avec d’autres bibliothèques, voici un exemple d’utilisation avec <a href="https://blog.jooq.org/2020/03/05/using-java-13-text-blocks-for-plain-sql-with-jooq">JOOQ</a>. </p>
<p>Avec cette seconde version, viennent des caractères d’échappement des lignes pour jongler avec les lignes trop longues ou gérer plus finement les retours à la ligne.</p>
<p>Dans l’exemple suivant toutes les lignes feront six caractères :</p>
<pre><code class="java"><span class="n">String</span> <span class="n">colors</span> <span class="o">=</span> <span class="s">"""</span>
<span class="s"> red \s</span>
<span class="s"> green\s</span>
<span class="s"> blue \s</span>
<span class="s"> """</span><span class="o">;</span></code></pre>
<h2 id="toc-les-mises-au-placard-et-lesdéparts">Les mises au placard et les départs</h2>
<p>Ironie de l’histoire, l’architecture créée par la même société que le langage est dépréciée et ne sera rapidement plus supportée. Pour les rares qui ont encore du Solaris et du <a href="https://fr.wikipedia.org/wiki/Architecture_SPARC">SPARC</a>, c’est bientôt la fin pour faire tourner des machines virtuelles Java (JVM) modernes. Les détails sont présents dans la <a href="https://openjdk.java.net/jeps/362">JEP 362</a>. Même processus pour le ramasse‑miettes <em>Concurrent Mark Sweep</em> dans le but de laisser plus de temps au développement des autres ramasse‑miettes, les détails dans la <a href="https://openjdk.java.net/jeps/291">JEP 291</a>.</p>
<p>Suppression des outils Pack200, suite à leur placardisation dans Java 11, ils sont remplacés par les outils <code>jlink</code>, plus d’informations dans la <a href="https://openjdk.java.net/jeps/367">JEP 367</a>.</p>
<h2 id="toc-dans-les-prochaines-versions">Dans les prochaines versions</h2>
<p>La seconde version du <em>pattern matching</em> de <em>instanceof</em>, les types scellés, la version définitive des blocs de texte. Je vous laisse regarder <a href="https://github.com/forax/do-synthetic-methods-dream-of-electric-switch-expressions/blob/master/slideshow/chapter09-future.ipynb">cette diapo</a> de Rémi Forax (un contributeur d’OpenJDK). Pour une vision plus « sous le capot », Brian Goetz (un architecte du langage) a rédigé <a href="http://cr.openjdk.java.net/%7Ebriangoetz/valhalla/sov/01-background.html">deux articles</a> sur les évolutions de Java.</p>
</div><div><a href="https://linuxfr.org/news/java-14-tombe-le-masque.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/119599/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/java-14-tombe-le-masque#comments">ouvrir dans le navigateur</a>
</p>
Nonolapérotheojouedubanjoolivier-mauryBenoît SibaudDavy DefaudYsabeau 🧶https://linuxfr.org/nodes/119599/comments.atomtag:linuxfr.org,2005:News/394422019-09-24T13:24:02+02:002019-09-26T13:54:58+02:00Communiquer avec D-Bus en Java avec JNIDBusLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Avec mes collègues chez <a href="http://viveris.fr">Viveris</a>, on s’est dit qu’on aimerait bien faire plus de logiciel libre. On a donc monté un « groupe <em>opensource</em> » dont le but est d’identifier les projets pour lesquels on peut publier tout ou une partie du code sous licence libre, et aussi de contribuer aux outils et bibliothèques qu’on utilise le plus.</p>
<p>Il y a quelques mois je vous présentais <a href="//linuxfr.org/users/pulkomandy/journaux/un-harnais-de-test-pour-qt">QTestFramework</a>, depuis on a également pu contribuer au <a href="https://github.com/whitequark/zmtp-wireshark">dissecteur 0MQ pour Wireshark</a> et <a href="https://github.com/viveris/jtag-boundary-scanner">un outil pour le <em>boundary scan</em> JTAG</a>.</p>
<p>On vient de publier il y a quelques jours une bibliothèque Java pour communiquer en D-Bus.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://opensource.viveris.fr" hreflang="en" href="https://linuxfr.org/redirect/104857">Projets opensource chez Viveris</a></li><li>lien nᵒ 2 : <a title="https://github.com/viveris/jnidbus" hreflang="en" href="https://linuxfr.org/redirect/104858">JNIDBus sur GitHub</a></li><li>lien nᵒ 3 : <a title="https://fr.wikipedia.org/wiki/D-Bus" hreflang="fr" href="https://linuxfr.org/redirect/104859">D-Bus sur Wikipédia</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#toc-contexte">Contexte</a><ul>
<li><a href="#toc-d-bus">D-Bus</a></li>
<li><a href="#toc-jni">JNI</a></li>
<li><a href="#toc-solutions-existantes-et-leurs-limitations">Solutions existantes et leurs limitations</a></li>
</ul>
</li>
<li>
<a href="#toc-jnidbus">JNIDBus</a><ul>
<li><a href="#toc-historique">Historique</a></li>
<li><a href="#toc-utilisation">Utilisation</a></li>
</ul>
</li>
</ul>
<h2 id="toc-contexte">Contexte</h2>
<h3 id="toc-d-bus">D-Bus</h3>
<p>D-Bus est un système de communication inter-processus utilisé sous GNU/Linux. Le projet a été lancé par des développeurs de Red Hat au sein de Freedesktop. Il a été intégré dans GNOME 2 et KDE 4, et aujourd’hui il est utilisé par de très nombreux composants d’un système GNU/Linux : systemd, NetworkManager et PulseAudio, par exemple. Il y a même une implémentation dans le noyau Linux lui‑même.</p>
<h3 id="toc-jni">JNI</h3>
<p>JNI (<em>Java Native Interface</em>) est une API qui permet d’interfacer du code tournant dans une machine virtuelle Java avec du code natif. Cela nécessite d’écrire (en C ou C++) des <em>wrappers</em> qui vont manipuler la pile de la JVM pour récupérer les arguments et pousser les valeurs de retour, et éventuellement accéder aux objets Java manipulés. Les méthodes ainsi implémentées peuvent ensuite être appelées depuis le code Java de façon transparente.</p>
<h3 id="toc-solutions-existantes-et-leurs-limitations">Solutions existantes et leurs limitations</h3>
<p>Freedesktop propose <a href="https://www.freedesktop.org/wiki/Software/DBusBindings/">DBus-Java</a>, mais il n’y a pas eu de version publiée depuis 2009. La dernière version a besoin de Java 7 pour fonctionner. De plus, cette bibliothèque implémente le protocole D-Bus en Java, ce qui risque de poser des problèmes d’interopérabilité avec l’implémentation en C.</p>
<p>Il existe bien <a href="https://github.com/hypfvieh/dbus-java">une version mise à jour</a> de la bibliothèque qui corrige au moins le premier problème, cependant l’API n’utilise pas les nouvelles fonctionnalités de Java et c’est bien dommage.</p>
<h2 id="toc-jnidbus">JNIDBus</h2>
<h3 id="toc-historique">Historique</h3>
<p>Dans le cadre d’une migration d’un de nos logiciels depuis Java 7, nous avons découvert que DBus-Java ne prenait pas en charge les versions plus récentes. Nous aurions pu nous contenter d’une mise à jour de cette implémentation, mais il y avait beaucoup de code à reprendre dedans et de toute façon, l’API ne nous convenait pas.</p>
<p>En effet, dbus-java représente les messages D-Bus par des « tuples » génériques, ce qui est assez peu pratique à utiliser et rend le code illisible. De plus, les API sont bloquantes et cela nous contraignait à utiliser une réserve (<em>pool</em>) de fils d’exécution qui complexifiait encore le logiciel.</p>
<p>L’ensemble des ces défauts et l’absence d’alternative viable nous ont poussé à développer notre propre alternative, en essayant de répondre a toutes les problématiques.</p>
<p>Afin de ne pas réimplémenter le protocole D-Bus nous voulions utiliser la bibliothèque <code>libdbus-1</code>. L’écosystème Java possède deux manières d’appeler du code natif : JNI et JNA, ce dernier étant écarté pour des raisons de performances et de complexité des bibliothèques de liaison (<em>bindings</em>) à écrire.</p>
<p>Enfin, la dernière contrainte était de réduire le code natif au strict minimum, afin de limiter la complexité de ce dernier qui est très difficile à tester unitairement.</p>
<h3 id="toc-utilisation">Utilisation</h3>
<p>La base de JNIDBus est la sérialisation d’objet Java. La signature du message est décrite dans une annotation.</p>
<p><em>Exemple pour un message contenant une chaîne de caractères et un entier :</em></p>
<pre><code class="java"><span class="nd">@DBusType</span><span class="o">(</span>
<span class="cm">/* Pour plus d’info sur le format de la signature, référez vous</span>
<span class="cm"> * à la documentation D-Bus</span>
<span class="cm"> */</span>
<span class="n">signature</span> <span class="o">=</span> <span class="s">"si"</span><span class="o">,</span>
<span class="cm">/* Donne le nom des propriétés contenant les données du message,</span>
<span class="cm"> * dans notre cas la chaîne de caractères est contenue dans la</span>
<span class="cm"> * propriété nommée « string » et l’entier dans le champs « integer »</span>
<span class="cm"> */</span>
<span class="n">fields</span> <span class="o">=</span> <span class="o">{</span><span class="s">"string"</span><span class="o">,</span><span class="s">"integer"</span><span class="o">}</span>
<span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringMessage</span> <span class="kd">extends</span> <span class="n">Message</span> <span class="o">{</span>
<span class="cm">/* Les champs seront accédés au travers de ses setters et</span>
<span class="cm"> * getters qui devront respecter la convention "setXxx"/"getXxx"</span>
<span class="cm"> */</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">string</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">integer</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getString</span><span class="o">()</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setString</span><span class="o">(</span><span class="n">String</span> <span class="n">string</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getInteger</span><span class="o">()</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setInteger</span><span class="o">(</span><span class="kt">int</span> <span class="n">string</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
<span class="o">}</span></code></pre>
<p>L’appel de méthodes distantes est transparent grâce a l’utilisation de <code>proxy</code> Java, il suffit de décrire l’interface de l’objet et de donner le nom de son bus pour pouvoir l’appeler. Toute méthode distante retourne un <code>PendingCall</code> auquel on doit attacher un <em>listener</em> pour être notifié de l’arrivée du résultat.</p>
<p>JNIDBus permet également d’exposer des méthodes distante par le biais de <code>handlers</code>. Un <em>handler</em> est simplement une classe annotée décrivant et implémentant les méthodes distantes, les signatures sont inférées grâce aux types d’entrées et de sorties. Les <em>handlers</em> seront exécutés dans la boucle d’évènements, il est donc primordial d’éviter tout appel bloquant ou toute tâche lourde. Afin de tout de même pouvoir effectuer ces tâches lourdes, les <em>handlers</em> gèrent un type de retour asynchrone (<code>Promise</code>).</p>
<p><em>Exemple d’un</em> handler <em>pour un signal et un appel :</em></p>
<pre><code class="java"><span class="nd">@Handler</span><span class="o">(</span>
<span class="cm">/* pour plus d’information référez vous à la documentation D-Bus</span>
<span class="cm"> */</span>
<span class="n">path</span> <span class="o">=</span> <span class="s">"/some/object/path"</span><span class="o">,</span>
<span class="n">interfaceName</span> <span class="o">=</span> <span class="s">"some.dbus.interface"</span>
<span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SomeHandler</span> <span class="kd">extends</span> <span class="n">GenericHandler</span> <span class="o">{</span>
<span class="nd">@HandlerMethod</span><span class="o">(</span>
<span class="c1">//le nom exposé a D-Bus peut être différent du nom de la méthode Java</span>
<span class="n">member</span> <span class="o">=</span> <span class="s">"someSignal"</span><span class="o">,</span>
<span class="n">type</span> <span class="o">=</span> <span class="n">HandlerType</span><span class="o">.</span><span class="na">SIGNAL</span>
<span class="o">)</span>
<span class="c1">//Ici notre signal n’a aucun paramètre, on utilise donc le singleton EmptyMessage</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">someSignal</span><span class="o">(</span><span class="n">Message</span><span class="o">.</span><span class="na">EmptyMessage</span> <span class="n">emptyMessage</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
<span class="nd">@HandlerMethod</span><span class="o">(</span>
<span class="n">member</span> <span class="o">=</span> <span class="s">"stringSignal"</span><span class="o">,</span>
<span class="n">type</span> <span class="o">=</span> <span class="n">HandlerType</span><span class="o">.</span><span class="na">METHOD</span>
<span class="o">)</span>
<span class="kd">public</span> <span class="n">SomeOutput</span> <span class="nf">someCall</span><span class="o">(</span><span class="n">SomeInput</span> <span class="n">input</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
<span class="o">}</span></code></pre>
<p><em>Comment enregistrer le handler auprès de D-Bus :</em></p>
<pre><code class="java"><span class="c1">//connection au bus</span>
<span class="n">Dbus</span> <span class="n">receiver</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Dbus</span><span class="o">(</span><span class="n">BusType</span><span class="o">.</span><span class="na">SESSION</span><span class="o">,</span><span class="s">"my.bus.name"</span><span class="o">);</span>
<span class="c1">//instanciation</span>
<span class="n">SomeHandler</span> <span class="n">handler</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SomeHandler</span><span class="o">();</span>
<span class="c1">//ajout, JNIDBus lancera une exception si le handler n’est pas valide</span>
<span class="k">this</span><span class="o">.</span><span class="na">receiver</span><span class="o">.</span><span class="na">addHandler</span><span class="o">(</span><span class="n">handler</span><span class="o">);</span></code></pre>
<p>Le langage Kotlin est pris en charge par le biais d’un artefact Gradle supplémentaire définissant des extensions qui suspendent l’appel de fonction et offrant la possibilité d’avoir des <code>handlers</code> qui facilitent la mise en place de cette suspension :</p>
<pre><code class="kotlin"><span class="c1">//il faut enregistrer la classe qui se chargera d’invoquer les méthodes qui suspendent</span>
<span class="n">KotlinMethodInvocator</span><span class="p">.</span><span class="n">registerKotlinInvocator</span><span class="p">()</span>
<span class="n">@Handler</span><span class="p">(</span><span class="n">path</span> <span class="p">=</span> <span class="s">"..."</span><span class="p">,</span> <span class="n">interfaceName</span> <span class="p">=</span> <span class="s">"..."</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">CallHandler</span> <span class="p">:</span> <span class="n">KotlinGenericHandler</span><span class="p">()</span> <span class="p">{</span>
<span class="n">@HandlerMethod</span><span class="p">(</span><span class="n">member</span> <span class="p">=</span> <span class="s">"suspendingCall"</span><span class="p">,</span> <span class="n">type</span> <span class="p">=</span> <span class="n">MemberType</span><span class="p">.</span><span class="n">METHOD</span><span class="p">)</span>
<span class="n">suspend</span> <span class="k">fun</span> <span class="nf">suspendingCall</span><span class="p">(</span><span class="n">emptyMessage</span><span class="p">:</span> <span class="n">Message</span><span class="p">.</span><span class="n">EmptyMessage</span><span class="p">):</span> <span class="n">SingleStringMessage</span> <span class="p">{</span>
<span class="c1">//coroutines are awesome</span>
<span class="n">delay</span><span class="p">(</span><span class="m">2000</span><span class="p">)</span>
<span class="k">return</span> <span class="n">SingleStringMessage</span><span class="p">().</span><span class="n">apply</span> <span class="p">{</span> <span class="n">string</span> <span class="p">=</span> <span class="s">"test"</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre>
</div><div><a href="https://linuxfr.org/news/communiquer-avec-d-bus-en-java-avec-jnidbus.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/118126/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/communiquer-avec-d-bus-en-java-avec-jnidbus#comments">ouvrir dans le navigateur</a>
</p>
pulkomandySeekDaSkyDavy DefaudYsabeau 🧶claudexNÿcoBAudhttps://linuxfr.org/nodes/118126/comments.atomtag:linuxfr.org,2005:News/394542019-09-24T09:51:26+02:002019-09-26T13:38:17+02:00Sortie d’OpenJDK 13Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Le 17 septembre 2019 est sortie cette nouvelle version d’OpenJDK. Elle comporte son lot de nouveautés, de fonctionnalités en préversion et des retraits. C’est aussi l’occasion de réécriture de certains composants, notamment <a href="https://openjdk.java.net/jeps/353">l’API Socket</a> pour l’inclusion des fils d’exécution — <em>threads</em> — locaux (<em>aka</em> <a href="https://openjdk.java.net/projects/loom/">Fibers</a>). Les notes de version vous permettront d’avoir plus de détails.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://jdk.java.net/13/release-notes" hreflang="en" href="https://linuxfr.org/redirect/104885">Notes de version</a></li><li>lien nᵒ 2 : <a title="https://adoptopenjdk.net/" hreflang="en" href="https://linuxfr.org/redirect/104886">AdoptOpenJDK</a></li><li>lien nᵒ 3 : <a title="https://www.youtube.com/watch?v=HrQWyS1EGLU" hreflang="fr" href="https://linuxfr.org/redirect/104891">Vidéo sur les dernières nouveautés et celles à venir</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#toc-dynamique-de-d%C3%A9veloppement">Dynamique de développement</a><ul>
<li><a href="#toc-contributions">Contributions</a></li>
<li><a href="#toc-rythme-de-publication-et-dur%C3%A9e-demaintenance">Rythme de publication et durée de maintenance</a></li>
</ul>
</li>
<li>
<a href="#toc-dans-les-%C3%A9pisodes-pr%C3%A9c%C3%A9dents">Dans les épisodes précédents</a><ul>
<li>
<a href="#toc-quelques-nouveaut%C3%A9s-apparues">Quelques nouveautés apparues</a><ul>
<li><a href="#toc-mot-clef-var">Mot clef « var »</a></li>
<li><a href="#toc-nouvelle-m%C3%A9thode-pour-les-collecteurs-collectorsteeing">Nouvelle méthode pour les collecteurs « Collectors::teeing »</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#toc-nouveaut%C3%A9s">Nouveautés</a><ul>
<li>
<a href="#toc-dynamic-cds-archive-jep350">Dynamic CDS Archive </a><a href="https://openjdk.java.net/jeps/350">JEP 350</a>
</li>
<li><a href="#toc-zgc-uncommit-unusedmemory">ZGC : uncommit unused memory</a></li>
<li><a href="#toc-divers">Divers</a></li>
</ul>
</li>
<li>
<a href="#toc-nouveaut%C3%A9s-en-pr%C3%A9version">Nouveautés en préversion</a><ul>
<li><a href="#toc-expressions-switch">Expressions switch</a></li>
<li><a href="#toc-text-block">Text Block</a></li>
</ul>
</li>
<li><a href="#toc-futur">Futur</a></li>
</ul>
<h2 id="toc-dynamique-de-développement">Dynamique de développement</h2>
<h3 id="toc-contributions">Contributions</h3>
<p>Bien qu’Oracle reste le principal contributeur au projet, depuis les dernières versions, Red Hat et d’autres sociétés prennent en charge une part significative du travail, aux environs de 30 % des tickets pour la version 13. Plus de détails dans les billets du blog d’Oracle concernant la sortie des versions <a href="https://blogs.oracle.com/java-platform-group/the-arrival-of-java-12">12</a> et <a href="https://blogs.oracle.com/java-platform-group/the-arrival-of-java-13">13</a>.</p>
<h3 id="toc-rythme-de-publication-et-durée-demaintenance">Rythme de publication et durée de maintenance</h3>
<p>Depuis la sortie d’OpenJDK 9, le rythme de publication est passé à une version tous les six mois avec une maintenance raccourcie pour les versions sans support étendu (actuellement 9, 10, 12 et 13). À l’heure actuelle, les versions 8 et 11 ont un support de longue durée. Selon les distributions du JDK (Red Hat, IBM, Azul, Amazon, etc.) c’est encore différent.</p>
<h2 id="toc-dans-les-épisodes-précédents">Dans les épisodes précédents</h2>
<h3 id="toc-quelques-nouveautés-apparues">Quelques nouveautés apparues</h3>
<h4 id="toc-mot-clef-var">Mot clef « var »</h4>
<p>La version 10 a vu l’apparition du mot clef <code>var</code> qui permet l’inférence de type et dont l’usage a été étendu aux <a href="https://fr.wikipedia.org/wiki/Lambda-calcul">expressions lambda</a> dans la version 11. Cela permet de ne pas avoir à déclarer le type s’il est évident ou d’avoir à écrire un type trop verbeux. Il existe une liste de bonnes pratiques (<a href="https://openjdk.java.net/projects/amber/LVTIstyle.html">ici</a> ou <a href="https://openjdk.java.net/projects/amber/LVTIFAQ.html">là</a>) pour éviter de rendre le code illisible.</p>
<h4 id="toc-nouvelle-méthode-pour-les-collecteurs-collectorsteeing">Nouvelle méthode pour les collecteurs « Collectors::teeing »</h4>
<p>Depuis la version 12, la méthode statique <code>Collectors::teeing</code> permet de récupérer dans un flux deux informations différentes et ensuite d’appeler une méthode pour exploiter les données obtenues. <a href="https://blog.codefx.org/java/teeing-collector/">Cet article</a> en anglais apporte plus de détails.</p>
<h2 id="toc-nouveautés">Nouveautés</h2>
<p>Dans cette version les évolutions définitives sont principalement des mises à jour côté sécurité, des correctifs divers et variés ainsi que des améliorations de la machine virtuelle Java (JVM).</p>
<h3 id="toc-dynamic-cds-archive-jep350">Dynamic CDS Archive <a href="https://openjdk.java.net/jeps/350">JEP 350</a>
</h3>
<p>C’est une extension d’un module libéré par Oracle dans le JDK 10 (<em>Application Class‑Data Sharing</em> <a href="https://openjdk.java.net/jeps/310">JEP 310</a>). Ce module permet des temps de chargement raccourcis et une empreinte mémoire plus faible en partageant certaines classes entre les processus Java. Cette extension simplifie l’usage du module grâce à quelques options :</p>
<ul>
<li>archivage à l’arrêt ;</li>
<li>chargement d’une archive au démarrage.</li>
</ul>
<h3 id="toc-zgc-uncommit-unusedmemory">ZGC : uncommit unused memory</h3>
<p>ZGC est un ramasse‑miettes expérimental à faible latence. Il est présent depuis le JDK 11. Désormais, la mémoire peut être rendue au système d’exploitation en configurant les options. C’est bien pratique puisque désormais la taille maximale du <a href="https://fr.wikipedia.org/wiki/Tas_(allocation_dynamique)">tas</a> (<em>heap</em>) est passée de 4 à 16 Tio.</p>
<h3 id="toc-divers">Divers</h3>
<p>Intégration d’Unicode 12.1, vous pourrez désormais avoir un émoji <a href="https://emojipedia.org/safety-vest/">gilet jaune</a>. Pour les personnes plus versées dans les aspects sécurité, la lecture du <a href="https://seanjmullan.org/blog/2019/08/05/jdk13">blog de Sean Mullan</a> est une bonne chose.</p>
<h2 id="toc-nouveautés-en-préversion">Nouveautés en préversion</h2>
<p>Il s’agit de fonctionnalités à découvrir et qui nécessitent une activation à la compilation. Elles sont d’ailleurs amenées à ne pas rester en l’état. Par exemple, les <em>switch expressions</em> en sont à leur seconde itération.</p>
<h3 id="toc-expressions-switch">Expressions switch</h3>
<p>Cette fonctionnalité est définie par la <a href="http://openjdk.java.net/jeps/325">JEP 325</a>. Il s’agit d’une des solutions pour rendre le code Java moins verbeux, et donc limiter le risque d’erreurs. Ainsi, le code :</p>
<pre><code class="java"><span class="k">switch</span> <span class="o">(</span><span class="n">day</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">MONDAY</span><span class="o">:</span>
<span class="k">case</span> <span class="n">FRIDAY</span><span class="o">:</span>
<span class="k">case</span> <span class="n">SUNDAY</span><span class="o">:</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">6</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="n">TUESDAY</span><span class="o">:</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">7</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="n">THURSDAY</span><span class="o">:</span>
<span class="k">case</span> <span class="n">SATURDAY</span><span class="o">:</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">8</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="n">WEDNESDAY</span><span class="o">:</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">9</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span></code></pre>
<p>Peut désormais s’écrire de la manière suivante :</p>
<pre><code class="java"><span class="k">switch</span> <span class="o">(</span><span class="n">day</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">MONDAY</span><span class="o">,</span> <span class="n">FRIDAY</span><span class="o">,</span> <span class="n">SUNDAY</span> <span class="o">-></span> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">6</span><span class="o">);</span>
<span class="k">case</span> <span class="n">TUESDAY</span> <span class="o">-></span> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">7</span><span class="o">);</span>
<span class="k">case</span> <span class="n">THURSDAY</span><span class="o">,</span> <span class="n">SATURDAY</span> <span class="o">-></span> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">8</span><span class="o">);</span>
<span class="k">case</span> <span class="n">WEDNESDAY</span> <span class="o">-></span> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">9</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<p>Ou encore si l’on veut affecter un résultat à une variable :</p>
<pre><code class="java"><span class="kt">int</span> <span class="n">numberOfLetters</span> <span class="o">=</span> <span class="k">switch</span> <span class="o">(</span><span class="n">dayOfWeek</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">MONDAY</span><span class="o">:</span>
<span class="k">case</span> <span class="n">FRIDAY</span><span class="o">:</span>
<span class="k">case</span> <span class="n">SUNDAY</span><span class="o">:</span>
<span class="n">yield</span> <span class="mi">6</span><span class="o">;</span>
<span class="k">case</span> <span class="n">TUESDAY</span>
<span class="n">yield</span> <span class="mi">7</span><span class="o">;</span>
<span class="k">case</span> <span class="n">THURSDAY</span>
<span class="k">case</span> <span class="n">SATURDAY</span>
<span class="n">yield</span> <span class="mi">8</span><span class="o">;</span>
<span class="k">case</span> <span class="n">WEDNESDAY</span>
<span class="n">yield</span> <span class="mi">9</span><span class="o">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalStateException</span><span class="o">(</span><span class="s">"Huh?: "</span> <span class="o">+</span> <span class="n">day</span><span class="o">);</span>
<span class="o">};</span></code></pre>
<h3 id="toc-text-block">Text Block</h3>
<p>Cette fonctionnalité est définie par la <a href="http://openjdk.java.net/jeps/355">JEP 355</a>. Les blocs de texte étaient initialement prévus pour la version 12 du JDK, mais au dernier moment ils ont été retirés faute de consensus sur le délimiteur et le comportement. L’idée est d’avoir du texte dont il est préférable de conserver le formatage pour des raisons de facilité d’écriture.<br>
Par exemple, au lieu d’écrire :</p>
<pre><code class="java"><span class="n">String</span> <span class="n">html</span> <span class="o">=</span> <span class="s">"<html>\n"</span> <span class="o">+</span>
<span class="s">" <body>\n"</span> <span class="o">+</span>
<span class="s">" <p>Hello, world</p>\n"</span> <span class="o">+</span>
<span class="s">" </body>\n"</span> <span class="o">+</span>
<span class="s">"</html>\n"</span><span class="o">;</span>
<span class="n">String</span> <span class="n">query</span> <span class="o">=</span> <span class="s">"SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n"</span> <span class="o">+</span>
<span class="s">"WHERE `CITY` = 'INDIANAPOLIS'\n"</span> <span class="o">+</span>
<span class="s">"ORDER BY `EMP_ID`, `LAST_NAME`;\n"</span><span class="o">;</span></code></pre>
<p>Il est possible d’écrire :</p>
<pre><code class="java"><span class="n">String</span> <span class="n">html</span> <span class="o">=</span> <span class="s">"""</span>
<span class="s"> <html></span>
<span class="s"> <body></span>
<span class="s"> <p>Hello, world</p></span>
<span class="s"> </body></span>
<span class="s"> </html></span>
<span class="s"> """</span><span class="o">;</span>
<span class="n">String</span> <span class="n">query</span> <span class="o">=</span> <span class="s">"""</span>
<span class="s"> SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`</span>
<span class="s"> WHERE `CITY` = 'INDIANAPOLIS'</span>
<span class="s"> ORDER BY `EMP_ID`, `LAST_NAME`;</span>
<span class="s"> """</span><span class="o">;</span></code></pre>
<p>Ce <a href="http://cr.openjdk.java.net/%7Ejlaskey/Strings/TextBlocksGuide_v9.html">guide exhaustif en anglais</a> à destination des développeurs décrit les cas d’usage avec les bonnes et les mauvaises pratiques.</p>
<h2 id="toc-futur">Futur</h2>
<p>Avec le nouveau rythme de publication des JDK, les nouveautés arrivent de manière plus progressive. Ainsi, dans les prochaines versions, voici les améliorations qui devraient rendre le langage meilleur :</p>
<ul>
<li>les <em><a href="https://openjdk.java.net/jeps/359">Records</a></em>, qui seront une sorte de <em>data class</em> telle que présente dans d’autres langages ;</li>
<li>les <em><a href="https://openjdk.java.net/jeps/360">Sealed type</a></em>, qui seront des types algébriques permettant de restreindre les possibilités ;</li>
<li>des <em><a href="https://openjdk.java.net/jeps/358">NullPointerException</a></em> plus explicites.</li>
</ul>
</div><div><a href="https://linuxfr.org/news/sortie-d-openjdk-13.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/118158/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-d-openjdk-13#comments">ouvrir dans le navigateur</a>
</p>
NonolapéroZeroHeuretheojouedubanjoYsabeau 🧶CeteraDavy DefaudJulien Jorgexofhttps://linuxfr.org/nodes/118158/comments.atomtag:linuxfr.org,2005:News/391112019-03-14T11:36:17+01:002019-03-18T08:12:27+01:00confusable-homoglyphs : une bibliothèque pour gérer les caractères qui se ressemblent<div><p>Bonjour tout le monde,</p>
<p>J’ai l’honneur de vous présenter une nouvelle bibliothèque Java (en fait compatible avec n’importe quel langage qui utilise la machine virtuelle Java, normalement) : <strong><a href="https://github.com/SpaceFox/confusable-homoglyphs">confusable-homoglyphs</a></strong>. « Nouvelle » dans sa version Java, car c’est en réalité <a href="https://github.com/vhf/confusable_homoglyphs">un portage d’une bibliothèque Python</a>. Notez qu’il en existe aussi une <a href="https://github.com/photogabble/php-confusable-homoglyphs">version PHP</a>.</p>
<p>C’est un outil sous licence Apache 2.0 qui permet de gérer directement au sein d’une application les caractères Unicode qui se ressemblent, et donc qui sont source de confusion.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://github.com/SpaceFox/confusable-homoglyphs" hreflang="en" href="https://linuxfr.org/redirect/103704">Dépôt Git de confusables-homoglyphs (Java)</a></li><li>lien nᵒ 2 : <a title="https://github.com/vhf/confusable_homoglyphs" hreflang="en" href="https://linuxfr.org/redirect/103705">Version Python (originale) de confusables_homoglyphs</a></li><li>lien nᵒ 3 : <a title="https://github.com/photogabble/php-confusable-homoglyphs" hreflang="en" href="https://linuxfr.org/redirect/103706">Portage en PHP de confusable-homoglyphs</a></li><li>lien nᵒ 4 : <a title="https://zestedesavoir.com/billets/3090/jai-porte-une-lib-python-en-java/" hreflang="fr" href="https://linuxfr.org/redirect/103707">Retour d’expérience sur le portage Python → Java</a></li></ul><div><h2 id="toc-quel-est-donc-le-but-de-cette-bibliothèque">Quel est donc le but de cette bibliothèque ?</h2>
<p>Les humains utilisent divers systèmes d’écriture, et ce qui devait arriver, arriva : il y a des caractères qui se ressemblent (voire qui sont graphiquement identiques, selon la police d’écriture), mais qui sont différents. Or, <a href="https://zestedesavoir.com/tutoriels/3039/linternationalisation-et-ses-pieges-creer-un-logiciel-universel/gerer-differentes-langues/#gestion-des-diacritiques">de telles confusions peuvent avoir des conséquences fâcheuses</a>, par exemple :</p>
<ul>
<li>l’utilisateur « ΑlaskaJazz » (le premier Α est un alpha majuscule grec) peut se faire passer pour l’utilisateur « AlaskaJazz » (uniquement des lettres latines) ;</li>
<li>on peut vous inciter à vous connecter sur <em><a href="http://www.micros%D0%BEft.com">www.microsоft.com</a></em> ou <em><a href="http://www.fa%CF%B2ebook.com">www.faϲebook.com</a></em> au lieu de <em><a href="http://www.microsoft.com">www.microsoft.com</a></em> ou <em><a href="http://www.facebook.com">www.facebook.com</a></em> ;</li>
<li>etc., on pourrait multiplier les exemples désagréables à l’infini.</li>
</ul>
<p>Si Unicode fournit des listes des caractères qui peuvent prêter à confusion, elles sont difficiles à utiliser en l’état : ce sont des fichiers textes avec un formatage particulier, qui plus est hébergés sur des serveurs instables et fréquemment hors ligne.</p>
<p>confusable-homoglyphs permet de gérer ces confusions en détectant et donnant des informations sur les caractères potentiellement problématiques.</p>
<h2 id="toc-daccord-mais-comment-ça-sutilise">D’accord, mais comment ça s’utilise ?</h2>
<p>La bibliothèque est disponible sur <a href="https://search.maven.org/artifact/fr.spacefox/confusable-homoglyphs">Maven Central</a> et donc s’importe comme n’importe quelle autre bibliothèque Java, ici avec Maven ou Gradle :</p>
<pre><code class="xml"><span class="nt"><dependency></span>
<span class="nt"><groupId></span>fr.spacefox<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>confusable-homoglyphs<span class="nt"></artifactId></span>
<span class="nt"><version></span>1.0.1<span class="nt"></version></span>
<span class="nt"></dependency></span></code></pre>
<pre><code class="gradle"><span class="n">compile</span> <span class="nl">group:</span> <span class="s1">'fr.spacefox'</span><span class="o">,</span> <span class="nl">name:</span> <span class="s1">'confusable-homoglyphs'</span><span class="o">,</span> <span class="nl">version:</span> <span class="s1">'1.0.1'</span></code></pre>
<p>Puis on initialise l’une des deux classes utilitaires, selon ce qu’on veut faire :</p>
<pre><code class="java"><span class="n">Categories</span> <span class="n">categories</span> <span class="o">=</span> <span class="n">Categories</span><span class="o">.</span><span class="na">fromInternal</span><span class="o">();</span>
<span class="n">Confusables</span> <span class="n">confusables</span> <span class="o">=</span> <span class="n">Confusables</span><span class="o">.</span><span class="na">fromInternal</span><span class="o">();</span>
<span class="c1">// ou si on préfère fournir un jeu de données spécifique :</span>
<span class="n">Categories</span> <span class="n">categories</span> <span class="o">=</span> <span class="n">Categories</span><span class="o">.</span><span class="na">fromJson</span><span class="o">(</span><span class="s">"/full/path/to/categories.json"</span><span class="o">);</span>
<span class="n">Confusables</span> <span class="n">confusables</span> <span class="o">=</span> <span class="n">fromJsons</span><span class="o">(</span><span class="s">"/full/path/to/categories.json"</span><span class="o">,</span> <span class="s">"/full/path/to/confusables.json"</span><span class="o">);</span>
<span class="c1">// (Confusables utilise Categories en interne).</span></code></pre>
<p>Et on utilise les objets créés. Il y a <a href="https://github.com/SpaceFox/confusable-homoglyphs#public-api">un résumé de l’API publique ici</a>. La création est relativement longue par rapport à l’utilisation, il vaut mieux garder ces objets vivants entre deux appels.</p>
<h2 id="toc-les-intentions-et-contraintes-du-projet">Les intentions et contraintes du projet</h2>
<p>En réalité, je n’ai pas besoin de cette bibliothèque, au‐delà du fait que je trouve qu’elle manque à Java. Je voulais aussi et surtout :</p>
<ul>
<li>connaître la difficulté à porter une bibliothèque de Python à Java ;</li>
<li>voir ce que c’est de créer un projet, seul, de A à Z et complet (avec documentation et tout) ;</li>
<li>essayer de déployer quelque chose sur Maven (en tant que fournisseur).</li>
</ul>
<p>Les contraintes que je me suis choisies pour ce projet étaient donc :</p>
<ul>
<li>licence libre (Apache 2.0) ;</li>
<li>Java 8, pour garder une bonne compatibilité avec les projets actuels et les différents langages qui utilisent la machine virtuelle Java ;</li>
<li>une API aussi proche de possible que l’originale (il y aura une version 2 avec des modifications dans cette API, un jour) ;</li>
<li>disponible sur Maven Central, pour être utilisable comme n’importe quelle bibliothèque Java ;</li>
<li>avec une doc complète ;</li>
<li>avec une couverture de tests correcte ;</li>
<li>avec de l’intégration continue via GitHub (j’ai toujours utilisé GitLab et GitLab CI pour mes autres projets Java).</li>
</ul>
<p>Et comme j’aime bien partager mon expérience, <a href="https://zestedesavoir.com/billets/3090/jai-porte-une-lib-python-en-java/">j’ai écrit un billet sur ce que j’ai tiré de celle‐ci</a>.</p>
<p>Je n’ai jamais eu l’occasion de vérifier que tout fonctionne bien sous Android. Si quelqu’un s’en sert dans cet environnement, que cette personne n’hésite pas à me faire signe. J’espère que ce petit utilitaire – ou les versions Python ou PHP – pourront vous servir un jour ! N’hésitez pas à créer tickets et demandes d’intégration (<em>pull requests</em>) si le cœur vous en dit !</p>
<hr>
<p>Cette dépêche est publiée sous licence <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.</p>
</div><div><a href="https://linuxfr.org/news/confusable-homoglyphs-une-bibliotheque-pour-gerer-les-caracteres-qui-se-ressemblent.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/116676/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/confusable-homoglyphs-une-bibliotheque-pour-gerer-les-caracteres-qui-se-ressemblent#comments">ouvrir dans le navigateur</a>
</p>
SpaceFoxXavier TeyssierDavy DefaudBenoît Sibaudhttps://linuxfr.org/nodes/116676/comments.atomtag:linuxfr.org,2005:News/385062018-11-09T08:05:21+01:002018-11-09T15:04:17+01:00Sortie de JDK 10Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Cette dépêche aura mis du temps à venir au monde, et depuis le JDK 11 — la version avec support étendu (LTS) — est sorti, mais il est encore temps de <s>troller</s>^W discuter de façon constructive de l’évolution d’un langage qui reste aujourd’hui au cœur des entreprises.</p>
<p>C’est l’occasion de (re)voir les ajouts côté langage, les changements et retraits côté API, les évolutions de la machine virtuelle Java (JVM), la gestion du code source ; le tout documenté au travers des <a href="https://en.wikipedia.org/wiki/JDK_Enhancement_Proposal">JEP</a> à la base des spécifications de Java.</p>
</div><ul><li>lien nᵒ 1 : <a title="http://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html" hreflang="en" href="https://linuxfr.org/redirect/101641">Notes de version</a></li><li>lien nᵒ 2 : <a title="http://openjdk.java.net/projects/jdk/10/" hreflang="en" href="https://linuxfr.org/redirect/101644">Liste des nouveautés</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#toc-c%C3%B4t%C3%A9-langage">Côté langage</a><ul>
<li><a href="#toc-un-ajout-linf%C3%A9rence-de-type-pour-les-variables-locales-jep286">Un ajout : l’inférence de type pour les variables locales (JEP 286)</a></li>
</ul>
</li>
<li>
<a href="#toc-c%C3%B4t%C3%A9-api">Côté API</a><ul>
<li>
<a href="#toc-changements">Changements</a><ul>
<li><a href="#toc-jep314">JEP 314</a></li>
</ul>
</li>
<li><a href="#toc-suppressions-apiobsol%C3%A8tes">Suppressions (API obsolètes)</a></li>
</ul>
</li>
<li>
<a href="#toc-c%C3%B4t%C3%A9-jvm">Côté JVM</a><ul>
<li><a href="#toc-jep304">JEP 304</a></li>
<li><a href="#toc-jep307">JEP 307</a></li>
<li><a href="#toc-jep310">JEP 310</a></li>
<li><a href="#toc-jep312">JEP 312</a></li>
<li><a href="#toc-jep316">JEP 316</a></li>
<li><a href="#toc-jep317">JEP 317</a></li>
</ul>
</li>
<li>
<a href="#toc-c%C3%B4t%C3%A9-code">Côté code</a><ul>
<li><a href="#toc-jep296">JEP 296</a></li>
<li><a href="#toc-jep313">JEP 313</a></li>
<li><a href="#toc-jep322">JEP 322</a></li>
<li><a href="#toc-jep319">JEP 319</a></li>
</ul>
</li>
</ul>
<h2 id="toc-côté-langage">Côté langage</h2>
<h3 id="toc-un-ajout-linférence-de-type-pour-les-variables-locales-jep286">Un ajout : l’inférence de type pour les variables locales (JEP 286)</h3>
<p>Il est désormais possible de déclarer des variables locales en remplaçant le type par le mot <code>var</code> afin de laisser le compilateur deviner le type :</p>
<pre><code class="java"><span class="c1">// ici, le compilo comprend que edt est de type Map<String, String></span>
<span class="n">var</span> <span class="n">edt</span> <span class="o">=</span> <span class="n">Map</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"lundi"</span><span class="o">,</span> <span class="s">"piscine"</span><span class="o">,</span> <span class="s">"mardi"</span><span class="o">,</span> <span class="s">"pétanque"</span><span class="o">);</span></code></pre>
<p>Ainsi, Java s’aligne sur de nombreux autres langages (sur la JVM, notamment Scala et Kotlin). Ce changement devrait inciter à éviter d’écrire des lignes à rallonge dont le seul but est d’éviter d’écrire les types des résultats intermédiaires. En effet, certains types peuvent être soit inconnus du programmeur (qui a la flemme d’ouvrir la Javadoc), soit très longs à écrire (types génériques), voire impossibles à écrire comme les types non dénotables, par exemple pour une classe anonyme :</p>
<pre><code class="java"><span class="n">var</span> <span class="n">x</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Object</span><span class="o">()</span> <span class="o">{</span> <span class="kt">int</span> <span class="n">a</span><span class="o">;</span> <span class="o">};</span> <span class="n">x</span><span class="o">.</span><span class="na">a</span> <span class="o">=</span> <span class="mi">42</span><span class="o">;</span></code></pre>
<p>Remarque : <code>var</code> n’est pas un mot-clé, mais un identifiant de type réservé. Ainsi, il est toujours possible de déclarer une variable ou une méthode de nom <code>var</code>… mais pas une classe !</p>
<h2 id="toc-côté-api">Côté API</h2>
<h3 id="toc-changements">Changements</h3>
<h4 id="toc-jep314">JEP 314</h4>
<p>On parle ici d’une amélioration sensible de l’internationalisation en s’appuyant sur des extensions d’Unicode. Voici la liste des nouvelles venues :</p>
<ul>
<li>
<code>cu</code> (type de devise, « <em>currency type</em>») ;</li>
<li>
<code>fw</code> (premier jour de la semaine, « <em>first day of week</em> ») ;</li>
<li>
<code>rg</code> (<em>region override</em>) ;</li>
<li>
<code>tz</code> (<em>time zone</em>).</li>
</ul>
<p>Tout ça va permettre aux classes de formatage (<code>java.text.DateFormat</code>, <code>java.text.NumberFormat</code>…) de récupérer directement les informations Unicode disponibles.</p>
<h3 id="toc-suppressions-apiobsolètes">Suppressions (API obsolètes)</h3>
<p>Suppression de l’attribut <code>java.lang.SecurityManager.inCheck</code>.<br>
Suppression des méthodes suivantes :</p>
<ul>
<li>
<code>java.lang.Runtime.getLocalizedInputStream(java.io.InputStream)</code> ;</li>
<li>
<code>java.lang.Runtime.getLocalizedOutputStream(java.io.OutputStream)</code> ;</li>
<li>
<code>java.lang.SecurityManager.classDepth(java.lang.String)</code> ;</li>
<li>
<code>java.lang.SecurityManager.classLoaderDepth()</code> ;</li>
<li>
<code>java.lang.SecurityManager.currentClassLoader()</code> ;</li>
<li>
<code>java.lang.SecurityManager.currentLoadedClass()</code> ;</li>
<li>
<code>java.lang.SecurityManager.getInCheck()</code> ;</li>
<li>
<code>java.lang.SecurityManager.inClass(java.lang.String)</code> ;</li>
<li>
<code>java.lang.SecurityManager.inClassLoader()</code>.</li>
</ul>
<h2 id="toc-côté-jvm">Côté JVM</h2>
<h3 id="toc-jep304">JEP 304</h3>
<p>Le ramasse‐miettes (<em>garbage collector</em>) est désormais défini par une interface plus propre, permettant dans le futur d’ajouter ou retirer plus facilement des implémentations de ramasse‐miettes. À noter que, dans cette version, les auteurs se sont contentés de faciliter ce travail, sans le mettre en œuvre.</p>
<h3 id="toc-jep307">JEP 307</h3>
<p>Le ramasse‐miettes par défaut (nommé « G1 » et promu à ce poste dans le JDK 9) est amélioré pour limiter les cas de latence, et ainsi limiter les impacts de la version précédente pour les utilisateurs. </p>
<h3 id="toc-jep310">JEP 310</h3>
<p>La mémoire consommée par des processus java est réduite en améliorant le partage de méta‐données. Cela a également un effet positif sur la vitesse de démarrage, avec des objectifs ambitieux : des lancements jusqu’à 20 à 30 % plus rapides, et une économie de 340 Mio sur des processus consommant 13 Gio. À noter que ce dernier chiffre concerne un cas de serveur d’applications faisant tourner six JVM.</p>
<h3 id="toc-jep312">JEP 312</h3>
<p>Pas mal d’actions émises par la JVM imposent aujourd’hui un arrêt de tous les fils d’exécution (<em>threads</em>) en cours. Cette JEP permet à la JVM d’arrêter un ou plusieurs fils d’exécution spécifiques, sans tout stopper.</p>
<p>Pour se figurer l’impact, il faut se dire qu’aujourd’hui la capture d’une pile d’appel complète — lors de l’interception d’une exception — imposait ce type de blocage complet. Désormais, seul un fil d’exécution sera interrompu, permettant au reste de l’application de continuer joyeusement sa route.</p>
<p>On va donc vers une réduction générale de la latence.</p>
<h3 id="toc-jep316">JEP 316</h3>
<p>L’idée ici est d’utiliser les nouvelles mémoires économiques de type NV-DIMM en permettant à l’utilisateur de spécifier son choix. Cela se fait, bien sûr non pas dans le code, mais dans les arguments de la JVM, sous la forme : <code>-XX:AllocateHeapAt=<path></code>.</p>
<p>En effet, ces mémoires sont typiquement accessibles via le système de fichiers, que ce soit sous <a href="https://channel9.msdn.com/events/build/2016/p470">Windows</a> ou <a href="https://lwn.net/Articles/618064">GNU/Linux</a>.</p>
<h3 id="toc-jep317">JEP 317</h3>
<p>Graal, un nouveau compilateur à la volée (JIT — <em>Just In Time</em> — en anglais) introduit dans le JDK 9 est désormais activable via des options de la ligne de commande, que voici :</p>
<pre><code>-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
</code></pre>
<p>Rien de réellement nouveau, mais cela va permettre d’avoir plus de testeurs (et donc d’améliorer la qualité). </p>
<h2 id="toc-côté-code">Côté code</h2>
<h3 id="toc-jep296">JEP 296</h3>
<p>Le code source de Java, jusqu’ici réparti dans huit dépôts Mercurial séparés, est regroupé au sein d’un dépôt unique. Pour les évolutions ou corrections qui touchent plusieurs composants (par exemple « jdk » et « langtools »), cela permettra d’avoir un seul <em>commit</em> atomique. Cela est cohérent, sachant que tous les composants suivaient le même cycle de vie de toute façon.</p>
<h3 id="toc-jep313">JEP 313</h3>
<p>Un peu de nettoyage avec le retrait de l’outil <em>javah</em>, qui n’était de toute façon plus utilisé depuis le JDK 9 et affichait des avertissements lorsqu’on l’invoquait. En charge de la génération de fichiers natifs d’en‐tête, cette fonction avait déjà été réimplémentée directement dans <em>javac</em> depuis le JDK 8.</p>
<h3 id="toc-jep322">JEP 322</h3>
<p>La numérotation des versions Java change ! On passe donc de :</p>
<pre><code>openjdk version "1.8.0_161"
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)
</code></pre>
<p>À ceci (pour l’exemple, on imagine un <em>build</em> 42 d’un JDK 11 LTS) :</p>
<pre><code>openjdk 11 2018-09-20 LTS
OpenJDK Runtime Environment (build 11+42-LTS)
OpenJDK 64-Bit Server VM (build 11+42-LTS, mixed mode)
</code></pre>
<p>Changement <em>a priori</em> cosmétique, mais qui pourrait avoir de lourdes conséquences… L’avenir répondra à cette question. En effet, beaucoup d’éditeurs de logiciels, font des tests assez fins sur les versions pour s’assurer que tel ou tel bogue ne risque pas de les affecter.</p>
<p>Pour les lecteurs de la Javadoc du JRE, l’étiquette <code>@since</code> reste alignée avec la propriété système <code>java.specification.version</code>. Et pour l’occasion, deux nouvelles propriétés sont ajoutées :</p>
<ul>
<li>
<code>java.version.date</code>, qui fournit la date de disponibilité de cette version ;</li>
<li>
<code>java.vendor.version</code>, optionnelle, pour la version spécifique d’un correctif de distribution GNU/Linux par exemple.</li>
</ul>
<h3 id="toc-jep319">JEP 319</h3>
<p>Jusqu’ici, le jeu de certificats déclaré dans le JDK était par défaut vide, obligeant un développeur à les rajouter. Désormais, un certain nombre d’autorités sont intégrées, dont notamment :</p>
<ul>
<li>Let’s encrypt ;</li>
<li>Digicert ;</li>
<li>Comodo ;</li>
<li>et quelques autres.</li>
</ul>
</div><div><a href="https://linuxfr.org/news/sortie-de-jdk-10.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/114014/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-jdk-10#comments">ouvrir dans le navigateur</a>
</p>
DringBAudAldooclaudexDavy DefaudZeroHeureLucasNonolapéroBruno Michelolivierwebhttps://linuxfr.org/nodes/114014/comments.atomtag:linuxfr.org,2005:News/384392018-02-13T08:12:57+01:002018-02-13T11:07:27+01:00Sortie de Pollen 3Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Après plus de 20 000 sondages créés, Pollen fait peau neuve !</p>
<p>Pollen est une plate‐forme de sondages libre (AGPL) développée en Java/JavaScript. Cette nouvelle mouture repense principalement l’ergonomie et le design de l’application et propose une API permettant d’interagir avec vos sondages depuis votre site Web.</p>
<p>Cette nouvelle version a fait l’objet d’une refonte importante de l’application. En ce sens, l’équipe de développement est à l’affût de tous vos retours ou commentaires.<br>
Un sondage Condorcet a été créé si vous souhaitez y jeter un œil : <a href="https://pollen.cl/#poll/3nFojtiES2OleB9nm94KAg/vote"><em>Quelle est votre distribution préférée ?</em></a></p></div><ul><li>lien nᵒ 1 : <a title="https://pollen.cl" hreflang="fr" href="https://linuxfr.org/redirect/101413">Site officiel</a></li><li>lien nᵒ 2 : <a title="https://linuxfr.org/news/pollen-un-nouveau-gestionnaire-de-sondages-libre" hreflang="fr" href="https://linuxfr.org/redirect/101414">LinuxFr.org : Pollen, un nouveau gestionnaire de sondages libre</a></li></ul><div><p>Historiquement, ce logiciel est né de la recherche de mise en œuvre d’un fonctionnement démocratique au sein de notre société. Nous souhaitions que chaque membre dispose du même droit à prendre part à chaque décision de la vie de l’entreprise (1 homme = 1 voix). Lorsqu’il n’y a pas unanimité dans une prise de décision, il nous fallait trouver un système efficace afin que chacun puisse exprimer rapidement son souhait. En ce sens, un système de vote binaire (oui/non) ou à choix unique ne pouvait pas convenir. Nous avions besoin de pouvoir exprimer des préférences.</p>
<p>Par exemple, voici une étude de l’augmentation de congés annuels, quatre choix sont possibles (il s’agit d’un exemple fictif) :</p>
<ul>
<li>pas d’augmentation ;</li>
<li>une journée supplémentaire ;</li>
<li>deux jours supplémentaires ;</li>
<li>une semaine supplémentaire.</li>
</ul><p>Dans cet exemple, l’un d’entre nous pourrait souhaiter en première intention que l’augmentation soit d’une semaine. En second choix, il souhaiterait que ce soit de deux jours, puis d’un jour et finalement pas d’augmentation en dernière alternative. Un second salarié pourrait souhaiter que l’augmentation des congés soit d’un ou deux jours sans réelle préférence. En revanche, ce salarié préférerait qu’il n’y ait pas d’augmentation plutôt que l’adoption d’une semaine supplémentaire, car il estime que ce serait trop pénalisant pour la société. Enfin, un dernier pourrait estimer qu’il ne souhaite pas d’augmentation des congés. Toutefois, si le consensus allait vers une augmentation, il préférerait que ce soit d’une ou deux journées. Seulement en dernier lieu, il souhaiterait que ce soit d’une semaine supplémentaire.</p>
<p>Par le vote Condorcet, Pollen nous permet d’exprimer facilement ce type de choix et de déterminer l’option la plus consensuelle. Par ailleurs, Pollen cherche également à répondre aux autres formes de sondages dont nous pourrions avoir besoin dans la vie de notre entreprise (élection d’un président avec un ou plusieurs tours, créer des collèges de votants, choix d’une date pour un rendez‐vous…). Bref, vous l’aurez compris, la diversité des modes de scrutins proposés (<a href="https://fr.wikipedia.org/wiki/M%C3%A9thode_de_Condorcet">Condorcet</a>, <a href="https://fr.wikipedia.org/wiki/M%C3%A9thode_Borda">Borda</a>, <a href="https://fr.wikipedia.org/wiki/M%C3%A9thode_de_Coombs">Coombs</a>, <a href="https://fr.wikipedia.org/wiki/Vote_alternatif">vote alternatif</a>, <a href="https://fr.wikipedia.org/wiki/Jugement_majoritaire">jugement majoritaire</a>…) est toujours partie intégrante de l’ADN de Pollen.</p>
<p>Une instance en ligne de Pollen est disponible et permet à tout un chacun d’y créer des sondages. Toutefois, l’application reste évidemment téléchargeable et installable sur un serveur privé.</p></div><div><a href="https://linuxfr.org/news/sortie-de-pollen-3.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/113723/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-pollen-3#comments">ouvrir dans le navigateur</a>
</p>
Samuel MaisonneuveDavy DefaudNils RatusznikXavier TeyssierZeroHeurehttps://linuxfr.org/nodes/113723/comments.atomtag:linuxfr.org,2005:News/384312018-02-06T16:29:15+01:002018-02-07T10:07:51+01:00Silverpeas 6.0 est (enfin) sorti !Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Après deux ans de travail acharné, tout en maintenant la 5.15, Silverpeas 6.0 est enfin sorti !</p>
<p>Silverpeas est un portail collaboratif et social pour faciliter la collaboration et l’échange d’informations entre les personnes à l’aide d’applications intégrées. Chaque application est construite sur cette idée de collaboration, de partage.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7777772e73696c766572706561732e6f72672f696d616765732f6c6f676f2e706e67/logo.png" alt="Logo de silverpeas" title="Source : https://www.silverpeas.org/images/logo.png"></p>
<p>Cette version majeure de Silverpeas contient des changements ergonomique, fonctionnels et surtout techniques. La version 6 repose désormais sur le serveur d’application <a href="http://wildfly.org/">Wildfly</a> (la 6.0 tourne sur la version 10.1.0 de celui‐ci), s’appuie sur <a href="https://docs.oracle.com/javaee/7/index.html">JEE 7</a> et <a href="http://www.oracle.com/technetwork/java/javase/overview/java8-2100321.html">Java 8</a>.</p></div><ul><li>lien nᵒ 1 : <a title="https://www.silverpeas.org" hreflang="en" href="https://linuxfr.org/redirect/101382">Silverpeas</a></li><li>lien nᵒ 2 : <a title="http://bit.ly/SilverpeasReleaseNote-6" hreflang="fr" href="https://linuxfr.org/redirect/101383">Les notes de version de la version 6.0</a></li><li>lien nᵒ 3 : <a title="https://www.silverpeas.org/installation/installationV6.html" hreflang="en" href="https://linuxfr.org/redirect/101384">La page d’installation de Silverpeas 6</a></li><li>lien nᵒ 4 : <a title="https://www.silverpeas.org/installation/izpack.html" hreflang="fr" href="https://linuxfr.org/redirect/101385">Pour juste tester Silverpeas 6</a></li><li>lien nᵒ 5 : <a title="https://hub.docker.com/_/silverpeas/" hreflang="fr" href="https://linuxfr.org/redirect/101386">Le dépôt Docker officiel de Silverpeas 6</a></li></ul><div><p>Silverpeas est un portail collaboratif et social. Son objectif est de faciliter la collaboration et l’échange d’informations et de connaissances entre les personnes et les équipes en leur offrant des applications intégrées diverses et variées comme des GED (<a href="https://fr.wikipedia.org/wiki/Gestion%20%C3%A9lectronique%20des%20documents" title="Définition Wikipédia">Gestion électronique des documents</a>), des forums, des agendas, des blogs et ainsi de suite. Chaque application est construite sur cette idée de collaboration, de partage. Ce n’est donc pas un pur système de gestion de contenu, ni une pure GED, ni un pur truc‐muche.</p>
<p>Cette nouvelle version majeure de Silverpeas s’accompagne d’un changement non seulement ergonomique et fonctionnel, mais aussi et surtout technique. Désormais, la nouvelle lignée de versions 6 repose sur le serveur d’application <a href="http://wildfly.org/">Wildfly</a> (la 6.0 tourne sur la version 10.1.0 de celui‐ci), s’appuie sur <a href="https://docs.oracle.com/javaee/7/index.html">JEE 7</a> et <a href="http://www.oracle.com/technetwork/java/javase/overview/java8-2100321.html">Java 8</a>. Le bus collaboratif a été revu et repose pleinement sur <a href="weld.cdi-spec.org">CDI</a> (<em>Context and Dependency Injection</em>) et ses possibilités. Le modèle métier de Silverpeas a aussi été amélioré. De nouveaux moteurs et API ou des grosses évolutions ont fait leur apparition, dont notamment :</p>
<ul>
<li>la gestion d’événements calendaires qui désormais motorise les applications <em>Almanach</em> (agenda collaboratif) et <em>Agenda Personnel</em> ;</li>
<li>la gestion des rappels ;</li>
<li>les notifications aux utilisateurs (qui utilisent le <em>Server Send Event</em>) ;</li>
<li>le rendu des pages dynamique par JavaScript ;</li>
<li>la prise en charge des vidéos ;</li>
<li>un moteur de <a href="https://fr.wikipedia.org/wiki/Workflow" title="Définition Wikipédia">Workflow</a> modernisé.</li>
</ul><p>Une refonte ergonomique a aussi été faite :</p>
<ul>
<li>les <em>frameset</em> ont été supprimés et désormais le rendu des différentes parties des pages Web se fait dynamiquement avec un nouveau moteur de rendu ; ce dernier est en constante évolution et toutes les pages ne sont pas encore gérées pleinement par celui‐ci ; toutefois, on peut constater et profiter d’un affichage et d’une interactivité plus fluide ;</li>
<li>l’utilisation des possibilités de HTML 5 avec notamment la lecture de vidéos ;</li>
<li>Un peaufinage de l’éditeur <a>[WYSIWYG]</a> avec justement la prise en charge des vidéos, de nouveaux thèmes ou encore de la sauvegarde en brouillon du contenu en rédaction afin de pouvoir le retrouver en cas de coupure de session ;</li>
<li>l’apparition d’indicateurs dynamiques (nombre d’utilisateurs connectés, de notifications non lues, d’affichage de notifications, etc.) ;</li>
<li>un nouveau look plus séduisant, Aurora ; celui‐ci ne fait pas partie de la distribution de base, mais il peut être installé facilement (reste la partie paramétrage à faire, plus fastidieuse) ;</li>
<li>les applications <em>Almanach</em> et <em>Agenda Personnel</em> reposent désormais sur le nouveau moteur de gestion d’événements calendaires avec son jeu de composants graphiques (<em>widgets</em>) prêts à emploi ;</li>
<li>une pagination bien plus performante (et surtout plus fluide).</li>
</ul><p>De nouveaux ajouts fonctionnels accompagnent aussi Silverpeas 6.0 :</p>
<ul>
<li>l’enrichissement des profils et des annuaires des utilisateurs à l’aide de formulaires (les champs fichier, image et vidéo ne sont pas encore pris en charge par cet enrichissement) ;</li>
<li>une uniformité entre l’agenda personnel et ceux collaboratifs, avec des liens pour passer de l’un à l’autre et la possibilité de retrouver dans son agenda personnel des événements des agendas collaboratifs auxquels on participe ;</li>
<li>Pouvoir importer ou synchroniser un agenda distant avec son agenda personnel. Le support aussi multi-agendas dans l’agenda personnel ;</li>
<li>la notification aux parties prenantes d’une modification de contenu, avec la possibilité de préciser la nature de celle‐ci et de rajouter cette précision en tant que commentaire à la contribution modifiée ;</li>
<li>la possibilité d’avoir une apparence différente par domaine d’utilisateurs ;</li>
<li>une messagerie instantanée basée sur <a href="https://www.jsxc.org">JSXC</a> et le protocole XMPP (actuellement elle utilise le serveur <a href="https://www.ejabberd.im/"><em>ejabberd</em></a>, qui nécessite d’être installé et configuré à part).</li>
<li>etc.</li>
</ul><p>Avec la version 6.0 de Silverpeas, un nouvel installateur et lanceur, basé sur <a href="https://gradle.org/">Gradle</a>, fait son apparition. Avec celui‐ci, il suffit de saisir la commande suivante pour installer Silverpeas (après avoir récupéré sa distribution) :</p>
<pre><code class="bash">$ ./silverpeas install</code></pre>
<p>Pour le mettre à jour vers une nouvelle version (après avoir mis à jour celle‐ci dans le fichier <code>silverpeas.gradle</code>) :</p>
<pre><code class="bash">$ ./silverpeas clean install</code></pre>
<p>(la commande <code>clean</code> est pour nettoyer l’installation précédente)</p>
<p>Pour lancer Silverpeas :</p>
<pre><code class="bash">$ ./silverpeas start</code></pre>
<p>Pour l’arrêter :</p>
<pre><code class="bash">$ ./silverpeas stop</code></pre>
<p>Toujours avec la version 6.0, si vous ne désirez pas récupérer la distribution de Silverpeas pour l’installer vous‐même à la main, une image Docker vous est proposée parmi les dépôts officiels Docker sur le <a href="https://hub.docker.com/_/silverpeas/">Docker Hub</a>.</p>
<p>De même, vous trouverez aussi, pour essayer Silverpeas, son <a href="http://www.silverpeas.org/files/Silverpeas-6.0-installer.jar">installateur IzPack</a>, mais aussi une image Docker dédiée à ça sur le <a href="https://hub.docker.com/r/silverpeas/silverpeas-test/">dépôt Docker de Silverpeas</a>.</p>
<p>Bref, que d’évolutions majeures pour commencer cette nouvelle lignée de Silverpeas. Un grand merci à sa communauté qui a aidé, testé et surtout supporté le développement de cette nouvelle version.</p></div><div><a href="https://linuxfr.org/news/silverpeas-6-0-est-enfin-sorti.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/113681/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/silverpeas-6-0-est-enfin-sorti#comments">ouvrir dans le navigateur</a>
</p>
Miguel MoquillonZeroHeureDavy Defaudpalm123https://linuxfr.org/nodes/113681/comments.atomtag:linuxfr.org,2005:News/369202015-12-01T16:00:44+01:002015-12-01T16:00:44+01:00Silverpeas 5.15 est sortie ... et la 6.0 est en préparationLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Champagne ! Après plus d'un an de développement, Silverpeas 5.15 est enfin sortie ! Jamais une version évolutive n'aura apporté autant de nouveautés. 75 pour être exact. Sans parler des nombreuses corrections de bogues (environ 76) Silverpeas est un portail collaboratif (gestion des connaissances, espaces collaboratifs métiers, publication et gestion de contenu web, …) fonctionnant sous J2EE, sous licence AGPL.</p>
<p>La version 5.15 devrait être la dernière de Silverpeas 5. En effet, en parallèle à sa réalisation, l'équipe derrière Silverpeas a aussi travaillé et continue à travailler sur la future version 6.0 qui débutera Silverpeas 6. C'est ce qui explique ce temps long. En fait, la majeure partie des nouvelles fonctionnalités de la 5.15 vient d'un report dans Silverpeas 5 de celles prévues pour la 6.0 afin que les utilisateurs existants puissent profiter aussi des nouveautés sans avoir à attendre et à installer la version 6.0.</p></div><ul><li>lien nᵒ 1 : <a title="http://www.silverpeas.org" hreflang="en" href="https://linuxfr.org/redirect/95766">Silverpeas</a></li><li>lien nᵒ 2 : <a title="https://extranet.silverpeas.com/silverpeas/LinkFile/Key/fc5749a3-5863-4864-99c8-2cef33a61f8f/SilverpeasV5.15_ReleaseNote.pdf" hreflang="fr" href="https://linuxfr.org/redirect/95767">La release note de la 5.15</a></li><li>lien nᵒ 3 : <a title="http://www.silverpeas.org/repo/index.html" hreflang="en" href="https://linuxfr.org/redirect/95768">Les paquets deb et rpm</a></li><li>lien nᵒ 4 : <a title="http://www.silverpeas.org/installation/installation.html" hreflang="en" href="https://linuxfr.org/redirect/95769">Installation en production</a></li></ul><div><p>Silverpeas 5.15 améliore l'expérience des utilisateurs qu'ils soient administrateurs fonctionnels ou techniques, contributeurs ou simples lecteurs :</p>
<ul>
<li>de nouvelles applications au catalogue : Boite à idées, Membres de l'espace, </li>
<li>des applications complètement remaniées : Actualités, Formulaires en ligne,</li>
<li>ou encore enrichies : la Galerie d'Images qui devient une Médiathèque,</li>
<li>des fonctionnalités transverses grandement améliorées : le glisser/déposer, l'édition en ligne, les abonnements, les notifications utilisateurs, …</li>
<li>enfin, un travail conséquent a été réalisé afin d'offrir une interface encore plus homogène et ergonomique.</li>
</ul><p>Depuis la première version, Silverpeas 5 n'a cessé de s'enrichir aussi bien du point de vue fonctionnel, ergonomique que technique. À tel point d'ailleurs que la version 5.15 aurait pu être à elle seule une version majeure. Il est temps désormais de passer à un nouveau jalon avec Silverpeas 6. Pour cette version, son socle technique sera rajeuni et modernisé ; il sera désormais basé, en partie, sur Wildfly et sur Java 8. Avec cette mouture, l'accent sera mis sur l'enrichissement conséquent de son interface de services Web de type REST et sur l'amélioration de l'interactivité entre applications. Mais ce qui va surtout changer c'est la direction, avant tout architectural, que prendra Silverpeas 6. Il est prévu en effet à terme de pouvoir découpler l'interface graphique Web du moteur de façon à ce que chacun puisse évoluer de son côté. À partir de là, il sera plus facile de refondre l'IHM en une application de type <a href="https://en.wikipedia.org/wiki/Single-page_application">Single-Page</a>, en partant sur une approche <a href="http://www.sei.cmu.edu/library/assets/presentations/nelson-saturn2013.pdf">SOFEA</a> (Service Oriented Front End Architecture).</p>
<p>Un grand merci à sa communauté sans qui cette version n'aurait pu être aussi riche.</p></div><div><a href="https://linuxfr.org/news/silverpeas-5-15-est-sortie-et-la-6-0-est-en-preparation.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/107506/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/silverpeas-5-15-est-sortie-et-la-6-0-est-en-preparation#comments">ouvrir dans le navigateur</a>
</p>
Miguel Moquillontuiu polbubar🦥Benoît Sibaudhttps://linuxfr.org/nodes/107506/comments.atomtag:linuxfr.org,2005:News/365982015-07-26T07:40:17+02:002015-07-26T07:40:17+02:00Développer des applications mobiles multiplateformes avec Java… avec le framework Codename OneLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Codename One est un framework permettant de développer en natif pour iOS, Android, BlackBerry et Windows Phone à partir d'un unique code Java.</p>
<p>Il est open-source (licence GPL avec exception Classpath) et se présente sous la forme d'un plug-in disponible pour les trois environnements de développement majeurs en Java (NetBeans, Eclipse, IntelliJ IDEA <em>(NdM: les deux premiers sont sous licence libre, le dernier existe en version "Community" libre et en version propriétaire)</em>. Il a pour particularité d’utiliser le cloud pour la compilation, ce qui évite aux développeurs d'avoir à installer divers SDK ou de posséder un système d’exploitation spécifique indispensable à la programmation des applications pour certaines plateformes mobiles. </p>
<p>Il a été créé par deux anciens ingénieurs d'Oracle, Chen Fishbein et Shai Almog, ceux-là mêmes qui mirent au point la bibliothèque d'interface graphique LWUIT, qui eut son âge d'or à l'heure où le J2ME régnait encore dans le monde de la téléphonie avant d'être détrôné par l'iPhone.</p></div><ul><li>lien nᵒ 1 : <a title="https://www.codenameone.com/index.html" hreflang="en" href="https://linuxfr.org/redirect/94650">Site officiel de Codename One</a></li><li>lien nᵒ 2 : <a title="http://codenameonefr.com/" hreflang="fr" href="https://linuxfr.org/redirect/94651">Site d'entraide francophone sur le framework Codename One</a></li><li>lien nᵒ 3 : <a title="http://www.d-booker.fr/content/74-codename-one-du-developpement-mobile-multiplate-forme-en-java" hreflang="fr" href="https://linuxfr.org/redirect/94652">Présentation de Codename One sur D-BookeR</a></li><li>lien nᵒ 4 : <a title="http://www.d-booker.fr/cn1/214-codename-one.html" hreflang="fr" href="https://linuxfr.org/redirect/94653">Le livre "Codename One - Développer en Java pour iOS, Android, Blackberry et Windows Phone"</a></li></ul><div><p>Codename One produit du code natif optimisé, assurant à ses applications de meilleures performances. <em>(NdM: l'accès au code source natif produit n'est pas fourni dans l'offre gratuite de Codename One)</em>.</p>
<p>Le plug-in est composé d'une API contenant toutes les classes nécessaires à la conception d'une application mobile, d'un designer, d'un simulateur pour tester les applications sur son ordinateur et du serveur de compilation dans le cloud.</p>
<p>L’une des grandes particularités de Codename One est son architecture dite « lightweight » qui apporte une meilleure solution aux problèmes de fragmentation des plateformes mobiles. Un composant lightweight dans ce cas-ci est un composant écrit entièrement en Java qui dessine sa propre interface tout en gérant ses propres événements et états. Cette manière de faire apporte un énorme avantage en termes de portabilité puisque le même code est exécuté sur toutes les plateformes en plus d’autres avantages. Les composants graphiques de Codename One sont personnalisables.</p>
<p>L’API de Codename One couvre de nombreuses fonctionnalités. On peut y trouver ce qu’il faut pour faire, par exemple, les tâches suivantes :</p>
<ul>
<li>l'interface graphique ;</li>
<li>la manipulation de la vidéo et de l’audio (enregistrement comme affichage) ;</li>
<li>le stockage ;</li>
<li>l'accès à la caméra ;</li>
<li>la manipulation d'une base de données SQLite ;</li>
<li>la manipulation des services web ;</li>
<li>le réseau ;</li>
<li>l'accès au cloud ;</li>
<li>la lecture des codes barres et QR codes ;</li>
<li>l’internationalisation et la localisation ;</li>
<li>les notifications ;</li>
<li>la manipulation des contacts ;</li>
<li>l'accès aux pages web ;</li>
<li>la monétisation ;</li>
<li>l’accès aux réseaux sociaux ;</li>
<li>la géolocalisation ;</li>
<li>les tests unitaires ;</li>
<li>la création de thèmes personnalisés ;</li>
<li>etc. </li>
</ul><p>Codename One est orienté exclusivement vers la conception d’applications métiers et n’a pas du tout été pensé pour créer des jeux. Quelques efforts sont en train d’être faits dans ce sens, mais rien de concret n’est encore disponible de ce côté.</p>
<p>Pour s'y former, vous disposez de la documentation officielle, complétée par de nombreux articles et tutoriels vidéo, ainsi qu'un forum très actif (en anglais). En outre, un livre vient de paraître en français aux éditions D-BookeR.</p></div><div><a href="https://linuxfr.org/news/developper-des-applications-mobiles-multiplateformes-avec-java-avec-le-framework-codename-one.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/106368/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/developper-des-applications-mobiles-multiplateformes-avec-java-avec-le-framework-codename-one#comments">ouvrir dans le navigateur</a>
</p>
pmdbrBenoît SibaudNils Ratusznikpatrick_gpalm123https://linuxfr.org/nodes/106368/comments.atomtag:linuxfr.org,2005:News/362612015-06-05T08:31:37+02:002015-06-05T08:31:37+02:00Modernisez votre code Java en un clic avec AutoRefactor v1.0.0 !Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Le 22 mars 2015 est sortie la version 1.0.0 du projet AutoRefactor. Ce logiciel est publié sous Eclipse Public License v1.0 et GNU General Public License v3+.</p>
<p>AutoRefactor restructure automatiquement le code source d'un programme Java afin de :</p>
<ul>
<li>Faciliter la maintenance en améliorant la lisibilité
<ul>
<li>exemple : lorsque toutes les branches d'un <code>if</code> ont les mêmes instructions à la fin des blocs, celles-ci sont déplacées après le <code>if</code>, …</li>
</ul>
</li>
<li>Moderniser le code
<ul>
<li>exemple : passer des APIs de java.util.Vector vers celle de java.util.List, …</li>
</ul>
</li>
<li>Appliquer les bonnes pratiques
<ul>
<li>exemple : utilisation d’accolades après un <code>if</code>, javadoc bien formés, bonne utilisation des APIs de BigDecimal, TestNG, …</li>
</ul>
</li>
<li>Réduire la taille du code
<ul>
<li>exemple : un <code>if</code> imbriqué dans un autre <code>if</code> devient un <code>if</code> unique, suppression des variables locales déclarées juste avant un <code>return</code>, …</li>
</ul>
</li>
<li>Améliorer les performances
<ul>
<li>exemple : utiliser Integer.valueOf(int) au lieu de new Integer(int), …</li>
</ul>
</li>
</ul></div><ul><li>lien nᵒ 1 : <a title="http://autorefactor.org/" hreflang="en" href="https://linuxfr.org/redirect/93478">Site officiel</a></li><li>lien nᵒ 2 : <a title="https://github.com/JnRouvignac/AutoRefactor" hreflang="en" href="https://linuxfr.org/redirect/93480">AutoRefactor sur Github</a></li><li>lien nᵒ 3 : <a title="http://www.alpesjug.fr/?p=2723" hreflang="fr" href="https://linuxfr.org/redirect/93481">Soirée Autorefactor à l'AlpesJUG 24/02/2015 – Le support</a></li><li>lien nᵒ 4 : <a title="http://autoRefactor.org/html/samples.html" hreflang="en" href="https://linuxfr.org/redirect/93701">Exemples de restructuration de code effectuées par AutoRefactor (tirés de la suite de tests)</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#historique">Historique</a></li>
<li><a href="#utilisation">Utilisation</a></li>
<li>
<a href="#principe-de-fonctionnement">Principe de fonctionnement</a><ul>
<li>
<a href="#syst%C3%A8me-de-passes-successives">Système de passes successives</a><ul>
<li><a href="#attention-il-faut-toujours-relire-le-code-modifi%C3%A9-automatiquement-avant-de-committer-les-changements">Attention ! Il faut toujours relire le code modifié automatiquement avant de committer les changements !</a></li>
<li><a href="#de-la-difficult%C3%A9-d%C3%A9crire-des-outils-automatiques-dans-un-monde-subjectif">De la difficulté d’écrire des outils automatiques dans un monde subjectif</a></li>
</ul>
</li>
<li><a href="#futur">Futur</a></li>
</ul>
</li>
<li><a href="#appel-%C3%A0-contributions">Appel à contributions</a></li>
</ul><h2 id="historique">Historique</h2>
<p>J'ai commencé ce projet car j'en avais assez de faire les mêmes changements manuellement (ou semi-manuellement avec les <em>refactorings</em> proposés par Eclipse) dans tous les fichiers sur lesquels je travaille. J'ai commencé par utiliser des expressions rationnelles pour retravailler toute la base de code, mais les faux positifs étaient bien trop nombreux, et puisque les expressions rationnelles ne travaillent que sur du texte, toute analyse s'appuyant sur la sémantique du langage (types, variables, etc.) est impossible. <br>
J'ai donc fait diverses expérimentations pour pouvoir faire des analyses « comprenant » le langage. Hélas toutes ces expérimentations ont raté. <br>
Toutes, jusqu’à ce que je crée un greffon Eclipse s'appuyant sur l'API des <em>Java Development Tools</em> (Eclipse JDT). Cette dernière fournit un <em>parser</em>, mais surtout une API pour faire des <em>refactorings</em>. En fait, c'est l'API que l'IDE Eclipse utilise pour ses propres <em>refactorings</em>.</p>
<h2 id="utilisation">Utilisation</h2>
<p>Depuis l'interface d'Eclipse, le développeur sélectionne les fichiers, <em>packages</em> ou projets Java à restructurer, et lance la réorganisation automatique du code. Pour cela, il choisit l’entrée <code>AutoRefactor</code> dans le menu contextuel accessible par un clic doit, ou bien il tape le raccourci clavier <code>Alt+Shift+Y</code>.<br>
Le greffon AutoRefactor restructure alors le code en appliquant automatiquement les <em>refactorings</em> choisis par le développeur.</p>
<h2 id="principe-de-fonctionnement">Principe de fonctionnement</h2>
<p>Les restructurations de code sont implémentées par des <em>refactorings</em> successifs, c'est-à-dire des petits changements incrémentaux qui modifient le code sans changer son comportement à l'exécution. Ceci est vrai pour la plupart des <em>refactorings</em>, ceci dit, certains peuvent avoir des effets de bord (voir ci-après), mais un programme sensible à ces changements s'expose à des comportements indéfinis lors de l’exécution.</p>
<h3 id="système-de-passes-successives">Système de passes successives</h3>
<p>Le greffon travaille avec un système de passes successives. Lorsque le développeur a choisi les règles de <em>refactoring</em> à appliquer, le greffon prend la liste des <em>refactorings</em> et (algorithme simplifié) :</p>
<ol>
<li>le fichier Java à analyser est parsé et produit un <a href="https://fr.wikipedia.org/wiki/arbre%20syntaxique%20abstrait" title="Définition Wikipédia">arbre syntaxique abstrait</a> (<em>AST</em> en anglais)</li>
<li>pour chaque <em>refactoring</em> :
<ol>
<li>cherche des opportunités de <em>refactoring</em> en <a href="https://fr.wikipedia.org/wiki/Visiteur_(patron_de_conception)">visitant</a> l'arbre syntaxique abstrait</li>
<li>génère les réécritures de code lorsqu'une opportunité de <em>refactoring</em> a été identifiée</li>
</ol>
</li>
<li>lorsque tout l'arbre syntaxique abstrait a été visité, si des réécritures de code ont été générées :
<ol>
<li>alors, toutes les réécritures de code générées sont appliquées sur le fichier</li>
<li>le fichier est sauvegardé</li>
<li>boucle vers 1. </li>
<li>sinon, fin : il n'y a plus de <em>refactorings</em> possibles sur ce fichier Java</li>
</ol>
</li>
</ol><p>Actuellement, tous les <em>refactorings</em> implémentés font du <a href="https://fr.wikipedia.org/wiki/filtrage%20par%20motif" title="Définition Wikipédia">filtrage par motif</a> (<em>pattern matching</em>) et travaillent fichiers par fichiers.</p>
<p>Du coup, il est extrêmement facile de paralléliser le code : le greffon lance autant de fils d’exécution en arrière-plan qu'il y a de processeurs disponibles et utilise une simple liste de tâches pour leur fournir du travail. Chaque tâche consiste à analyser et restructurer un fichier Java.</p>
<p>Bien sûr, le greffon dispose d'une suite de tests composée de paires de fichiers exemples Java : un fichier avant restructuration, un autre fichier contenant le résultat que l'on souhaite obtenir après restructuration. La suite de tests unitaires exécute chaque règle de <em>refactoring</em> indépendamment sur sa paire de fichiers et compare la sortie attendue avec la sortie obtenue. Les deux doivent correspondre. La compilation et les tests unitaires sont exécutés sur un serveur d’intégration continue.<br>
Je vous encourage très vivement à <strong>regarder les <a href="http://autorefactor.org/html/samples.html">exemples tirés de la suite de tests</a></strong>.</p>
<p>Par ailleurs, je teste plus avant les <em>refactorings</em> sur la base de code mature d'<a href="//linuxfr.org/news/opendj-2-6-pour-faire-swinguer-vos-annuaires-ldap">OpenDJ</a>. Cela me permet de trouver pas mal de bugs avant qu'ils n'atteignent une version stable et donc de rajouter des cas de tests. Le code mature est bien plus sournois que les cas de tests auxquels on peut penser ! :) </p>
<h4 id="attention-il-faut-toujours-relire-le-code-modifié-automatiquement-avant-de-committer-les-changements">Attention ! Il faut toujours relire le code modifié automatiquement avant de committer les changements !</h4>
<p>En effet, voici un exemple de code pour lequel les changements ont modifié le comportement :</p>
<pre><code class="java"><span class="n">Integer</span> <span class="n">i1</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="n">Integer</span> <span class="n">i2</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Integer</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">i1</span> <span class="o">==</span> <span class="n">i2</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// compare des références d'objets !</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"OK"</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<p>Ici, "<code>OK</code>" n'est pas affiché sur le terminal car <code>i1</code> et <code>i2</code> sont deux objets différents en mémoire.<br>
Maintenant si AutoRefactor modifie le code comme ceci :</p>
<pre><code class="java"><span class="n">Integer</span> <span class="n">i1</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="n">Integer</span> <span class="n">i2</span> <span class="o">=</span> <span class="n">Integer</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">i1</span> <span class="o">==</span> <span class="n">i2</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// compare des références d'objets !</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"OK"</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<p>"<code>OK</code>" sera affiché sur le terminal car <code>i1</code> et <code>i2</code> référencent le même objet en mémoire.<br>
Comment est-ce possible ? Et bien la ligne <code>Integer i1 = 0;</code> est en fait générée comme ceci par le compilateur java : <code>Integer i1 = Integer.valueOf(0);</code>. De plus il existe un cache pour les objets <code>Integer</code> entre -128 et 127 (inclus), ce qui fait que <code>i1</code> et <code>i2</code> référencent le même objet en mémoire.<br>
Ce code aurait probablement du être écrit comme ceci :</p>
<pre><code class="java"><span class="kt">int</span> <span class="n">i1</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">i2</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">i1</span> <span class="o">==</span> <span class="n">i2</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// compare la valeur des entiers !</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"OK"</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<p>Et le code aurait correctement affiché "<code>OK</code>" sur le terminal.<br>
AutoRefactor ne sait pas encore le faire, mais j’espère y arriver un jour.</p>
<p>Cet exemple démontre que certains <em>refactorings</em> ne préservent pas totalement le comportement lorsque le code s'appuie sur des comportements « limites » de Java.<br>
Cependant il est possible que ce soit bien le comportement désiré par le programmeur.</p>
<p>C'est pourquoi il est recommandé de toujours relire les <em>refactorings</em> automatiques avant des les committer dans le gestionnaire de sources. Vous utilisez bien un gestionnaire de source, n'est-ce pas ?</p>
<h4 id="de-la-difficulté-décrire-des-outils-automatiques-dans-un-monde-subjectif">De la difficulté d’écrire des outils automatiques dans un monde subjectif</h4>
<p>Après avoir mis ce gros bémol, je tiens à signaler que j'essaie d’avoir un résultat final propre et logique. Je suis pragmatique : soit j'essaie absolument de préserver le comportement du programme, et dans ce cas, je ne fais presque rien ; soit je prends des risques « mesurés » en ignorant les cas « bêtes » comme celui-ci dessus, et alors j'autorise beaucoup plus de possibilités de <em>refactorings</em>.<br>
C'est un équilibre dur à trouver dans certains cas tel qu'illustré par la méthode <a href="https://github.com/JnRouvignac/AutoRefactor/blob/master/plugin/src/main/java/org/autorefactor/refactoring/rules/SimplifyExpressionRefactoring.java#L163"><code>isHardToRead()</code></a>. Bien sûr, c'est éminemment subjectif, mais puisque c'est moi qui code, j'impose mes idées. :) Plus sérieusement, si vous pensez que j'ai tort, je suis ouvert à discussion.</p>
<p>J'avais d'ailleurs pensé rajouter une préférence pour forcer à préserver le comportement, mais j'ai renoncé lorsque je me suis rendu compte du nombre de <em>refactorings</em> que cela interdirait. Par exemple, un code aussi simple que celui-ci :</p>
<pre><code class="java"><span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"this is "</span> <span class="o">+</span> <span class="n">obj</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span></code></pre>
<p>ne pourrait plus être réécrit comme ceci :</p>
<pre><code class="java"><span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"this is "</span> <span class="o">+</span> <span class="n">obj</span><span class="o">);</span></code></pre>
<p>En effet, on perdrait la vérification sur référence nulle. Si <code>obj</code> est <code>null</code>, la première écriture lève une <code>NullPointerException</code>, alors que la deuxième écriture imprime "<code>this is null</code>". Bien sur, il serait peut-être possible de détecter qu'<code>obj</code> n'est pas <code>null</code> en faisant une analyse du flot de contrôle (j'ai bien dit peut-être), mais cela nécessite des outils dont je ne dispose pas encore. Par pragmatisme, j'ai simplement considéré que s’appuyer sur un appel à <code>toString()</code> pour détecter une référence nulle était une mauvaise pratique dans ce cas, et j'ai quand même écrit la règle qui fait cette réécriture :)</p>
<h3 id="futur">Futur</h3>
<p>Même si tous les <em>refactorings</em> actuellement implémentés font du filtrage par motif, j’espère bien parvenir un jour à faire de l'analyse de flot de contrôle en construisant un <a href="https://fr.wikipedia.org/wiki/graphe%20de%20flot%20de%20contr%C3%B4le" title="Définition Wikipédia">graphe de flot de contrôle</a> (<em>CFG</em> an anglais). Ceci permettrait d’écrire des <em>refactorings</em> comprenant les chemins d’exécution du code, comme le ferait un développeur qui lirait du code. En particulier, il deviendrait possible de réduire la portée des variables, comprendre quels chemins d’exécution du code sont morts (impossibles à atteindre)</p>
<p> </p>
<p>J'aimerai aussi développer une autre fonctionnalité : l'extraction (semi-?)automatique de méthodes.<br>
Voici un exemple de code que je vois trop souvent :</p>
<pre><code class="java"> <span class="c1">// ... quelques dizaines / centaines de lignes de code</span>
<span class="kt">boolean</span> <span class="n">found</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">s</span> <span class="o">:</span> <span class="n">strings</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">toFind</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="n">s2</span><span class="o">))</span> <span class="o">{</span>
<span class="n">found</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">if</span> <span class="o">(</span><span class="n">found</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// faire quelque chose</span>
<span class="o">}</span>
<span class="c1">// ... quelques dizaines / centaines de lignes de code</span></code></pre>
<p>Comment simplifier cette longue méthode ?<br>
En extrayant une nouvelle méthode, comme ceci :</p>
<pre><code class="java"> <span class="c1">// ... quelques dizaines / centaines de lignes de code</span>
<span class="k">if</span> <span class="o">(</span><span class="n">containsIgnoreCase</span><span class="o">(</span><span class="n">strings</span><span class="o">,</span> <span class="n">toFind</span><span class="o">))</span> <span class="o">{</span>
<span class="c1">// faire quelque chose</span>
<span class="o">}</span>
<span class="c1">// ... quelques dizaines / centaines de lignes de code</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kt">boolean</span> <span class="nf">containsIgnoreCase</span><span class="o">(</span><span class="n">Collection</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">strings</span><span class="o">,</span> <span class="n">String</span> <span class="n">toFind</span><span class="o">)</span> <span class="o">{</span>
<span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">s</span> <span class="o">:</span> <span class="n">strings</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">toFind</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="n">s2</span><span class="o">))</span> <span class="o">{</span>
<span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span></code></pre>
<p>La plus grosse difficulté, c'est de savoir comment nommer la nouvelle méthode, et un humain doit intervenir, d’où le coté semi-automatique.</p>
<p> </p>
<p>Le support de Java 7 arrive doucement avec le support de <em>refactorings</em> générant l'opérateur diamant '<code><></code>' (pas de besoin de répéter les types génériques), et le <em>multi-catch</em> (pas besoin de copier-coller le même bout de code dans deux blocs <em>catch</em> différents).<br>
Par exemple, le code suivant :</p>
<pre><code class="java"><span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">strings</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o"><</span><span class="n">String</span><span class="o">>();</span>
<span class="k">try</span> <span class="o">{</span>
<span class="c1">// plus de code</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">IllegalArgumentException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">NullPointerException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span></code></pre>
<p>Peut être réécrit comme ceci en Java 7 :</p>
<pre><code class="java"><span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">strings</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o"><>();</span>
<span class="k">try</span> <span class="o">{</span>
<span class="c1">// plus de code</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">IllegalArgumentException</span> <span class="o">|</span> <span class="n">NullPointerException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span></code></pre>
<p>La version 1.1.0 à venir a beaucoup de bonnes et nouvelles choses disponibles. Je vous conseille de l'installer depuis les <em>nightlies</em>.</p>
<h2 id="appel-à-contributions">Appel à contributions</h2>
<p>J’espère que la présentation de ce greffon vous aura intéressé.</p>
<p>Si vous êtes un développeur Java, je vous encourage à l'installer :</p>
<ul>
<li>Depuis l'<em>update site</em> <a href="http://autorefactor.org/releases/">http://autorefactor.org/releases/</a>
</li>
<li>Depuis l'Eclipse marketplace: </li>
<li>
<strong>Pour les aventureux, installez une nightly</strong> depuis l'<em>update site</em> <a href="http://autorefactor.org/nightly/">http://autorefactor.org/nightly/</a>
</li>
</ul><p>Si vous êtes vraiment enthousiasmés et que vous voudriez l’améliorer ou l'adapter à vos besoins, n’hésitez surtout pas ! Envoyez des rapports de bugs, des <em>pull-requests</em>, interagissez sur gitter, etc.</p>
<p>Si vous voulez aider, mais que vous êtes à court d’idées, voici une petite liste :</p>
<ul>
<li>Testez le logiciels sur de grosses bases de code anciennes. C'est là où se cachent les surprises. :)</li>
<li>Je suis aussi intéressé par des retours d’expériences, blog posts ou autres… Faites connaître ce greffon auprès de vos collègues !</li>
<li>
<a href="https://github.com/JnRouvignac/AutoRefactor/issues">J'ai plein d’idées dans le <em>bug tracker</em></a>, mais pas assez de temps pour les implémenter. Si jamais le cœur vous en dit…</li>
<li><a href="http://autorefactor.org">Le site web est moche, et a besoin d'amour</a></li>
<li>
<a href="https://github.com/JnRouvignac/AutoRefactor-Logo">Le greffon n'a pas encore de logo malgré mes misérables tentatives</a>.</li>
</ul><p>Je m'amuse bien à réécrire le code automatiquement. Franchement, ce n'est pas trop difficile ou trop long d'ajouter de nouvelles règles, alors n’hésitez pas à vous lancer ! Je vous aiderai.</p></div><div><a href="https://linuxfr.org/news/modernisez-votre-code-java-en-un-clic-avec-autorefactor-v1-0-0.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/105182/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/modernisez-votre-code-java-en-un-clic-avec-autorefactor-v1-0-0#comments">ouvrir dans le navigateur</a>
</p>
djanopalm123BAudSnarkNÿcoBenoît Sibaudhttps://linuxfr.org/nodes/105182/comments.atomtag:linuxfr.org,2005:News/353932014-05-21T16:42:35+02:002014-05-22T08:56:23+02:00Sortie de LDAP Synchronization Connector 2.1.0Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Le logiciel <a href="http://www.lsc-project.org">LDAP Synchronization Connector</a> est un moteur de synchronisation entre annuaires LDAP, bases de données, fichiers, et autres sources (API REST, etc.). Il est particulièrement efficace pour diffuser les données d'utilisateurs et de groupes entre son annuaire d'entreprise, un serveur Active Directory, une base de données d'application. On peut le classer dans la catégorie des logiciels de <a href="http://fr.wikipedia.org/wiki/M%C3%A9ta-annuaire" title="Définition Wikipédia">Méta-annuaire</a> ou de gestionnaire d'identités (IDM en anglais).</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f6c73632d70726f6a6563742e6f72672f77696b692f5f6d656469612f6c73635f70726f6a6563745f6c6f676f5f7265642e706e67/lsc_project_logo_red.png" alt="logo LSC" title="Source : http://lsc-project.org/wiki/_media/lsc_project_logo_red.png"></p>
<p>La version 2.1.0 vient d'être publiée, avec son lot de nouveautés et de correctifs, décrits dans la suite de la dépêche.</p>
<p><em>Ndm : LSC est livré sous licence <a href="http://opensource.org/licenses/bsd-license.php">BSD</a>.</em></p></div><ul><li>lien nᵒ 1 : <a title="http://tools.lsc-project.org/news/49" hreflang="en" href="https://linuxfr.org/redirect/90559">Annonce de la sortie sur la forge du projet</a></li><li>lien nᵒ 2 : <a title="http://lsc-project.org/wiki/download" hreflang="en" href="https://linuxfr.org/redirect/90560">Téléchargement</a></li><li>lien nᵒ 3 : <a title="http://lsc-project.org" hreflang="fr" href="https://linuxfr.org/redirect/90561">Site web</a></li><li>lien nᵒ 4 : <a title="http://linuxfr.org/news/lsc-un-nouveau-logiciel-dalimentation-dannuaire" hreflang="fr" href="https://linuxfr.org/redirect/90562">Dépêche sur la sortie de LSC 1.0</a></li><li>lien nᵒ 5 : <a title="http://fr.slideshare.net/ldapcon/synchronize-ad-and-openldap-with-lsc" hreflang="en" href="https://linuxfr.org/redirect/90563">Conférence LSC à la LDAPCon 2013</a></li></ul><div><h2 id="scripts-javascript-et-groovy">Scripts Javascript et Groovy</h2>
<p>Pour configurer les règles d'association d'attributs entre source et destination, ou les conditions de création/modification/suppression/renommage d'entrées, LSC permet d'utiliser des langages de script comme Javascript et Groovy.</p>
<p>La version 2.1.0 améliore ce support de plusieurs manières :</p>
<ul>
<li>le debugger Rhino peut être activé grâce au préfixe <code>rdjs:</code>
</li>
<li>des fichiers externes peuvent être utilisés pour simplifier le code écrit dans la configuration XML.</li>
</ul><h2 id="paquets">Paquets</h2>
<p>LSC est désormais livré sous forme de paquets Rpm et Debian en plus de la distribution traditionnelle. Des dépôts Yum et Apt ont été mis en place, il n'y a donc plus d'excuse pour ne pas l'installer.</p>
<h2 id="correctifs">Correctifs</h2>
<p>De nombreux bogues ont été corrigés dans cette nouvelle version, en particulier sur la gestion des attributs binaires, sur l'encodage des DN et le mode dry-run. La liste complète des changements est visible sur la <a href="http://tools.lsc-project.org/versions/show/55">forge du projet</a></p>
<h2 id="greffons">Greffons</h2>
<p>LSC possède un système de greffons encore peu exploité jusqu'ici. Ces greffons permettent d'ajouter des sources et/ou des destinations possibles pour les connecteurs. Les greffons disponibles pour la version 2.1 sont :</p>
<ul>
<li>Exécutable: lance des scripts pour chaque action de synchronisation</li>
<li>NIS: interroge un annuaire NIS (Yellow Pages)</li>
<li>OBM: met à jour les utilisateurs et les groupes dans <a href="http://www.obm.org">OBM</a>
</li>
</ul></div><div><a href="https://linuxfr.org/news/sortie-de-ldap-synchronization-connector-2-1-0.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/102245/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-ldap-synchronization-connector-2-1-0#comments">ouvrir dans le navigateur</a>
</p>
OUDOT ClémentZeroHeureBenoît Sibaudclaudexpalm123tuiu polhttps://linuxfr.org/nodes/102245/comments.atomtag:linuxfr.org,2005:News/353392014-05-06T08:58:52+02:002014-05-06T16:21:31+02:00OpenJDK JEP 180: HashMap, collisions & attaques par la complexitéLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Cette dépêche parle de la <a href="http://openjdk.java.net/jeps/180">JEP 180</a> d'OpenJDK 8 qui propose une solution intéressante aux problèmes d'attaques sur la complexité que rencontrent les tables de hachage.</p>
<p>On a déjà parlé de ce sujet <a href="//linuxfr.org/users/alenvers/journaux/des-tables-de-hachage-en-milieu-hostile">ici même</a> à <a href="//linuxfr.org/news/le-colonel-moutarde-sur-la-table-de-hachage-avec-un-livre-de-maths">plusieurs reprises</a>. Je vais cependant rapidement représenter le problème et l'évolution des discussions. Le lecteur averti sur le sujet ira directement au dernier paragraphe pour voir la proposition de la JEP 180.</p>
<p><abbr title="Note des modérateurs">NdM</abbr> : merci à ckyl pour son journal.</p></div><ul><li>lien nᵒ 1 : <a title="http://linuxfr.org/users/cykl/journaux/openjdk-jep-180-hashmap-collisions-attaques-par-la-complexite" hreflang="fr" href="https://linuxfr.org/redirect/90359">Journal à l'origine de la dépêche</a></li><li>lien nᵒ 2 : <a title="http://linuxfr.org/news/openjdk-8-jep-142-false-sharing" hreflang="fr" href="https://linuxfr.org/redirect/90376">Dépêche précédente sur la JEP 142</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#pr%C3%A9sentation-des-tables-de-hachage">Présentation des tables de hachage</a></li>
<li><a href="#attaques-par-la-complexit%C3%A9">Attaques par la complexité</a></li>
<li><a href="#java-7u6--alternative-string-hashing">Java 7u6 & « alternative string-hashing »</a></li>
<li><a href="#attaques-par-la-complexit%C3%A9-bis">Attaques par la complexité (bis)</a></li>
<li>
<a href="#jep-180-une-solution-int%C3%A9ressante">JEP 180: Une solution intéressante</a><ul>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</li>
</ul><h2 id="présentation-des-tables-de-hachage">Présentation des tables de hachage</h2>
<p>Une table de hachage est une implémentation du type abstrait tableau associatif. Un <a href="http://fr.wikipedia.org/wiki/Tableau_associatif">tableau associatif</a> permet d'associer une clé à une ou plusieurs valeurs, on le nomme aussi parfois dictionnaire. Il fait partie des types abstraits les plus utilisés avec les listes.</p>
<p>Une table de hachage est une implémentation particulière d'un tableau associatif. Elle est aussi la plus courante. Basiquement il s'agit d'un tableau dont les cases contiennent un pointeur vers nil, un élément ou une liste d'élément. On détermine la case à utiliser en appliquant une fonction de hachage à la clé. Idéalement, chaque case ne pointera que vers un unique élément. Dans ce cas les opérations d'insertion, de consultation et de suppression se font en temps constant, noté <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMzEiIHN0cm9rZS13aWR0%0AaD0iMTAiIGQ9Ik0zOTQgMGgtMjc2djE1Yzc0IDQgOTUgMjUgOTUgODB2NDQ5%0AYzAgMzQgLTkgNDkgLTMwIDQ5Yy0xMCAwIC0yNyAtNSAtNDUgLTEybC0yNyAt%0AMTB2MTRsMTc5IDkxbDkgLTN2LTU5N2MwIC00MyAyMCAtNjEgOTUgLTYxdi0x%0ANVoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTi0zMSIgeD0iMTA2%0ANSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTMxIj48L3VzZT48%0AdXNlIGhyZWY9IiNTVElYV0VCTUFJTi0yOSIgeD0iMTU3MCIgeT0iMCIgeGxp%0Abms6aHJlZj0iI1NUSVhXRUJNQUlOLTI5Ij48L3VzZT48L2c+PC9zdmc+%0A" alt="O(1)">, c'est à dire qui ne dépend pas du nombre d'éléments présents dans la table de hachage. Cependant si la fonction de hachage retourne deux fois la même valeur pour deux clés différentes, ce que l'on nomme collision, alors les deux valeurs sont généralement stockées comme une liste. C'est à dire que maintenant il va falloir parcourir toute cette liste. Dans le pire cas, la fonction de hachage retourne toujours la même valeur, toutes les valeurs vont donc être stockées dans la même case et l'on va devoir parcourir la liste pour chaque opération. La complexité est alors linéaire par rapport au nombre d'éléments dans la structure, noté <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48L2RlZnM+PGcgc3Ryb2tlPSJibGFjayIgZmlsbD0iYmxh%0AY2siIHN0cm9rZS13aWR0aD0iMCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAg%0ALTEgMCAwKSI+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU5JLTRGIiB4bGluazpo%0AcmVmPSIjU1RJWFdFQk1BSU5JLTRGIj48L3VzZT48dXNlIGhyZWY9IiNTVElY%0AV0VCTUFJTi0yOCIgeD0iNzI3IiB5PSIwIiB4bGluazpocmVmPSIjU1RJWFdF%0AQk1BSU4tMjgiPjwvdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RSIg%0AeD0iMTA2NSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RSI+%0APC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU4tMjkiIHg9IjE1NzAiIHk9%0AIjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTi0yOSI+PC91c2U+PC9nPjwv%0Ac3ZnPg==%0A" alt="O(n)">, ce qui est très peu performant. Une table de hachage a donc une complexité moyenne d'<img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMzEiIHN0cm9rZS13aWR0%0AaD0iMTAiIGQ9Ik0zOTQgMGgtMjc2djE1Yzc0IDQgOTUgMjUgOTUgODB2NDQ5%0AYzAgMzQgLTkgNDkgLTMwIDQ5Yy0xMCAwIC0yNyAtNSAtNDUgLTEybC0yNyAt%0AMTB2MTRsMTc5IDkxbDkgLTN2LTU5N2MwIC00MyAyMCAtNjEgOTUgLTYxdi0x%0ANVoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTi0zMSIgeD0iMTA2%0ANSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTMxIj48L3VzZT48%0AdXNlIGhyZWY9IiNTVElYV0VCTUFJTi0yOSIgeD0iMTU3MCIgeT0iMCIgeGxp%0Abms6aHJlZj0iI1NUSVhXRUJNQUlOLTI5Ij48L3VzZT48L2c+PC9zdmc+%0A" alt="O(1)"> mais un pire cas en <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48L2RlZnM+PGcgc3Ryb2tlPSJibGFjayIgZmlsbD0iYmxh%0AY2siIHN0cm9rZS13aWR0aD0iMCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAg%0ALTEgMCAwKSI+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU5JLTRGIiB4bGluazpo%0AcmVmPSIjU1RJWFdFQk1BSU5JLTRGIj48L3VzZT48dXNlIGhyZWY9IiNTVElY%0AV0VCTUFJTi0yOCIgeD0iNzI3IiB5PSIwIiB4bGluazpocmVmPSIjU1RJWFdF%0AQk1BSU4tMjgiPjwvdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RSIg%0AeD0iMTA2NSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RSI+%0APC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU4tMjkiIHg9IjE1NzAiIHk9%0AIjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTi0yOSI+PC91c2U+PC9nPjwv%0Ac3ZnPg==%0A" alt="O(n)">. Il est donc crucial d'avoir une fonction de hachage performante. Les personnes n'étant pas à l'aise avec l'implémentation d'une table de hachage ou les concepts précédant auront tout intérêt à consulter la page <a href="http://fr.wikipedia.org/wiki/Table_de_hachage">Wikipédia</a> qui est assez complète.</p>
<p>Cet article s'accompagne d'un benchmark écrit avec <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> qui va nous permettre d'observer comment se comporte la classe <a href="http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html">HashMap</a> de Java dans différentes circonstances. Le code de ce benchmark est extrêmement simple:</p>
<pre><code class="java"> <span class="nd">@GenerateMicroBenchmark</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">put</span><span class="o">()</span> <span class="o">{</span>
<span class="n">HashMap</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">map</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
<span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="nl">s:</span> <span class="n">strings</span><span class="o">)</span> <span class="o">{</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">s</span><span class="o">,</span> <span class="n">s</span><span class="o">);</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">map</span><span class="o">.</span><span class="na">size</span><span class="o">();</span>
<span class="o">}</span></code></pre>
<p>Nous insérons une collection de chaîne de caractère dans une HashMap et nous mesurons le temps moyen de cette opération. Mesurer l'insertion est une métrique correcte pour ce que nous souhaitons mesurer car lors d'une insertion, dans le cas où la clé existe déjà il faut remplacer la valeur existante. Il faut donc rechercher parmi toutes les clés déjà existantes dans cette case. Les comportements en consultation et en suppressions seront similaires à celui que nous observons. Dans tous les cas, en cas de collision, il faudra traverser toutes les valeurs de cette case. Exemple du code de la méthode <em>put()</em>:</p>
<pre><code class="java"> <span class="kd">public</span> <span class="n">V</span> <span class="nf">put</span><span class="o">(</span><span class="n">K</span> <span class="n">key</span><span class="o">,</span> <span class="n">V</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">key</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span>
<span class="k">return</span> <span class="nf">putForNullKey</span><span class="o">(</span><span class="n">value</span><span class="o">);</span>
<span class="kt">int</span> <span class="n">hash</span> <span class="o">=</span> <span class="n">hash</span><span class="o">(</span><span class="n">key</span><span class="o">.</span><span class="na">hashCode</span><span class="o">());</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">indexFor</span><span class="o">(</span><span class="n">hash</span><span class="o">,</span> <span class="n">table</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="n">Entry</span><span class="o"><</span><span class="n">K</span><span class="o">,</span><span class="n">V</span><span class="o">></span> <span class="n">e</span> <span class="o">=</span> <span class="n">table</span><span class="o">[</span><span class="n">i</span><span class="o">];</span> <span class="n">e</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span> <span class="n">e</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="na">next</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Object</span> <span class="n">k</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">hash</span> <span class="o">==</span> <span class="n">hash</span> <span class="o">&&</span> <span class="o">((</span><span class="n">k</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="na">key</span><span class="o">)</span> <span class="o">==</span> <span class="n">key</span> <span class="o">||</span> <span class="n">key</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">k</span><span class="o">)))</span> <span class="o">{</span>
<span class="n">V</span> <span class="n">oldValue</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="na">value</span><span class="o">;</span>
<span class="n">e</span><span class="o">.</span><span class="na">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
<span class="n">e</span><span class="o">.</span><span class="na">recordAccess</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="k">return</span> <span class="n">oldValue</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="n">modCount</span><span class="o">++;</span>
<span class="n">addEntry</span><span class="o">(</span><span class="n">hash</span><span class="o">,</span> <span class="n">key</span><span class="o">,</span> <span class="n">value</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span></code></pre>
<p>On peut clairement y voir les étapes suivantes:</p>
<ul>
<li>On calcule le <code>hash</code> de la clé, qui va déterminer la case <code>i</code>
</li>
<li>On itère sur toutes les clés présentes dans la case <code>i</code> pour regarder si une correspond à <code>key</code>
<ul>
<li>Si oui, alors on remplace la valeur existante par <code>value</code>
</li>
<li>Sinon, on ajoute un nouvel élément pour cette clé à la fin de la liste</li>
</ul>
</li>
</ul><p>Comme on le voit avec la ligne suivante <code>int hash = hash(key.hashCode());</code>, en Java la case est calculée à partir de la valeur retournée par <code>hashCode()</code>. On applique en plus la fonction <code>hash()</code> afin d'améliorer un peu la distribution des clés. En effet, <code>i</code> est calculé modulo la taille de la table qui est une puissance de deux, et il est facile d'avoir des effets néfastes:</p>
<pre><code class="java"> <span class="cm">/**</span>
<span class="cm"> * Applies a supplemental hash function to a given hashCode, which</span>
<span class="cm"> * defends against poor quality hash functions. This is critical</span>
<span class="cm"> * because HashMap uses power-of-two length hash tables, that</span>
<span class="cm"> * otherwise encounter collisions for hashCodes that do not differ</span>
<span class="cm"> * in lower bits. Note: Null keys always map to hash 0, thus index 0.</span>
<span class="cm"> */</span>
<span class="kd">static</span> <span class="kt">int</span> <span class="nf">hash</span><span class="o">(</span><span class="kt">int</span> <span class="n">h</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// This function ensures that hashCodes that differ only by</span>
<span class="c1">// constant multiples at each bit position have a bounded</span>
<span class="c1">// number of collisions (approximately 8 at default load factor).</span>
<span class="n">h</span> <span class="o">^=</span> <span class="o">(</span><span class="n">h</span> <span class="o">>>></span> <span class="mi">20</span><span class="o">)</span> <span class="o">^</span> <span class="o">(</span><span class="n">h</span> <span class="o">>>></span> <span class="mi">12</span><span class="o">);</span>
<span class="k">return</span> <span class="n">h</span> <span class="o">^</span> <span class="o">(</span><span class="n">h</span> <span class="o">>>></span> <span class="mi">7</span><span class="o">)</span> <span class="o">^</span> <span class="o">(</span><span class="n">h</span> <span class="o">>>></span> <span class="mi">4</span><span class="o">);</span>
<span class="o">}</span></code></pre>
<p>Enfin le cas qui va nous intéresser particulièrement ici est celui des chaines de caractères comme clé car c'est une utilisation extrêmement courante et exposée aux attaques. Souvent les données fournies par l'utilisateur sont des chaînes de caractères plutôt que des objets complexes. Par exemple les en-tête HTTP sont souvent stockés dans un tableau associatif.</p>
<p>Regardons donc comment est implémenté le <code>hashCode</code> de la classe <code>String</code>:</p>
<pre><code class="java"> <span class="cm">/**</span>
<span class="cm"> * Returns a hash code for this string. The hash code for a</span>
<span class="cm"> * <code>String</code> object is computed as</span>
<span class="cm"> * <blockquote><pre></span>
<span class="cm"> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]</span>
<span class="cm"> * </pre></blockquote></span>
<span class="cm"> * using <code>int</code> arithmetic, where <code>s[i]</code> is the</span>
<span class="cm"> * <i>i</i>th character of the string, <code>n</code> is the length of</span>
<span class="cm"> * the string, and <code>^</code> indicates exponentiation.</span>
<span class="cm"> * (The hash value of the empty string is zero.)</span>
<span class="cm"> *</span>
<span class="cm"> * @return a hash code value for this object.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">hashCode</span><span class="o">()</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">h</span> <span class="o">=</span> <span class="n">hash</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">count</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">h</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">off</span> <span class="o">=</span> <span class="n">offset</span><span class="o">;</span>
<span class="kt">char</span> <span class="n">val</span><span class="o">[]</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">len</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">h</span> <span class="o">=</span> <span class="mi">31</span><span class="o">*</span><span class="n">h</span> <span class="o">+</span> <span class="n">val</span><span class="o">[</span><span class="n">off</span><span class="o">++];</span>
<span class="o">}</span>
<span class="n">hash</span> <span class="o">=</span> <span class="n">h</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">h</span><span class="o">;</span>
<span class="o">}</span></code></pre>
<p>Cela correspond à une fonction de hachage non cryptographique très courante pour les chaînes de caractères. C'est une variante du <em>Bernstein hash</em>, aussi appelé djb2. Elle a ceci d'intéressant qu'elle est utilisée par beaucoup de plateformes et qu'expliquer pourquoi elle marche et comment et pourquoi ont été choisies les valeurs est assez difficile. Les gens intéressés pourront découvrir d'<a href="http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx">autres fonctions</a> ainsi que passer beaucoup de temps à chercher les réponses à la question précédente.</p>
<p>Dans tous les cas nous appellerons cette variante de dbj2 sous le doux nom de DJBX31A.</p>
<p>Maintenant exécutons notre benchmark en utilisant Java 6u45 avec des chaines aléatoires de taille constante, 15 caractères, pour des collections allant de 10 à 30.000 éléments. Le résultat est le suivant:</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f31305f312e706e673f7261773d74727565/JEP_180_analysis_10_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_10_1.png?raw=true"></p>
<p>Dans ce cas nous avons le comportement normal attendu. Il y a peu de collisions. En moyenne le temps d'insertion est constant et ne dépend pas de la taille de la collection, <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMzEiIHN0cm9rZS13aWR0%0AaD0iMTAiIGQ9Ik0zOTQgMGgtMjc2djE1Yzc0IDQgOTUgMjUgOTUgODB2NDQ5%0AYzAgMzQgLTkgNDkgLTMwIDQ5Yy0xMCAwIC0yNyAtNSAtNDUgLTEybC0yNyAt%0AMTB2MTRsMTc5IDkxbDkgLTN2LTU5N2MwIC00MyAyMCAtNjEgOTUgLTYxdi0x%0ANVoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTi0zMSIgeD0iMTA2%0ANSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTMxIj48L3VzZT48%0AdXNlIGhyZWY9IiNTVElYV0VCTUFJTi0yOSIgeD0iMTU3MCIgeT0iMCIgeGxp%0Abms6aHJlZj0iI1NUSVhXRUJNQUlOLTI5Ij48L3VzZT48L2c+PC9zdmc+%0A" alt="O(1)">. Nous voyons donc que la courbe est linéaire puisque nous répétons <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiAxLjcxNGV4OyBoZWlnaHQ6IDEuNzE0ZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC4xNDNleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9Ii0xNSAtNjc5%0ALjI1ODEyMzI1NTE1NDkgNzQ3IDcyMC41MTYyNDY1MTAzMSIgeG1sbnM9Imh0%0AdHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZGVmcyBpZD0iTWF0aEpheF9T%0AVkdfZ2x5cGhzIj48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTRFIiBzdHJva2Ut%0Ad2lkdGg9IjEwIiBkPSJNNzI3IDY1M3YtMTZjLTYzIC0xNCAtNjUgLTE2IC0x%0AMDIgLTE0NWwtMTQ2IC01MDdoLTE4bC0yMzAgNTUwbC0xMTQgLTQyMmMtNiAt%0AMjEgLTkgLTQxIC05IC01NGMwIC0yOCAxOCAtMzkgNzAgLTQzdi0xNmgtMTk4%0AdjE2YzU2IDggNzAgMjQgMTA2IDE1MmwxMTcgNDE1Yy0xNSAzNSAtMzkgNTQg%0ALTg2IDU0djE2aDE2MGwyMDcgLTQ5OWwxMDYgMzg4YzYgMjEgOCAzMiA4IDQ0%0AYzAgMzYgLTEyIDQ2IC02OSA1MXYxNmgxOThaIj48L3BhdGg+PC9kZWZzPjxn%0AIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAi%0AIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAgMCkiPjx1c2UgaHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RSIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS00%0ARSI+PC91c2U+PC9nPjwvc3ZnPg==%0A" alt="N"> fois une opération prenant un temps donné. Nous voyons aussi que nous arrivons à insérer environ 20 000 éléments par milliseconde.</p>
<h2 id="attaques-par-la-complexité">Attaques par la complexité</h2>
<p>Si vous avez bien suivi la première partie, vous savez que la performance d'une table de hachage dépend du nombre de collisions et donc de la qualité de sa fonction de hachage. Par nature une table de hachage ne permet pas de garantir que les opérations seront en <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMzEiIHN0cm9rZS13aWR0%0AaD0iMTAiIGQ9Ik0zOTQgMGgtMjc2djE1Yzc0IDQgOTUgMjUgOTUgODB2NDQ5%0AYzAgMzQgLTkgNDkgLTMwIDQ5Yy0xMCAwIC0yNyAtNSAtNDUgLTEybC0yNyAt%0AMTB2MTRsMTc5IDkxbDkgLTN2LTU5N2MwIC00MyAyMCAtNjEgOTUgLTYxdi0x%0ANVoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTi0zMSIgeD0iMTA2%0ANSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTMxIj48L3VzZT48%0AdXNlIGhyZWY9IiNTVElYV0VCTUFJTi0yOSIgeD0iMTU3MCIgeT0iMCIgeGxp%0Abms6aHJlZj0iI1NUSVhXRUJNQUlOLTI5Ij48L3VzZT48L2c+PC9zdmc+%0A" alt="O(1)">, il s'agit seulement du cas moyen quand tout se passe bien. La performance au pire cas est <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48L2RlZnM+PGcgc3Ryb2tlPSJibGFjayIgZmlsbD0iYmxh%0AY2siIHN0cm9rZS13aWR0aD0iMCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAg%0ALTEgMCAwKSI+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU5JLTRGIiB4bGluazpo%0AcmVmPSIjU1RJWFdFQk1BSU5JLTRGIj48L3VzZT48dXNlIGhyZWY9IiNTVElY%0AV0VCTUFJTi0yOCIgeD0iNzI3IiB5PSIwIiB4bGluazpocmVmPSIjU1RJWFdF%0AQk1BSU4tMjgiPjwvdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RSIg%0AeD0iMTA2NSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RSI+%0APC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU4tMjkiIHg9IjE1NzAiIHk9%0AIjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTi0yOSI+PC91c2U+PC9nPjwv%0Ac3ZnPg==%0A" alt="O(n)">.</p>
<p>Ce fait est connu de tout étudiant ayant suivi une introduction à l'algorithmique. Seulement il y a quelques années certains ont eu l'idée d'utiliser ce pire cas pour faire des dénis de service. C'est une attaque par la complexité. L'idée est simple, beaucoup d'applications stockent en mémoire des chaînes de caractères fournies par un utilisateur dans une table de hachage. S'il arrive à fournir des chaînes qui vont systématiquement créer des collisions, alors il va pouvoir ralentir très fortement le système.</p>
<p>L'idée n'est pas nouvelle, elle a été parfaitement <a href="http://madchat.fr/reseau/dos/CrosbyWallach_UsenixSec2003.pdf">documentée</a> en 2003 par Scott A. Crosby et Dan S. Wallach lors de l'Usenix-Sec. Ils avaient alors étudié Perl, qui avait réagi et fourni un correctif. Tout le monde a alors oublié cette histoire pendant quelques années.</p>
<p>En 2011, Alexander Klink et Julian Wälde se souviennent de cette histoire et partent alors explorer ce qu'il est possible de faire avec presque 10 ans après. Les <a href="http://events.ccc.de/congress/2011/Fahrplan/attachments/2007_28C3_Effective_DoS_on_web_application_platforms.pdf">slides</a> du 28C3 décrivent très bien ce qu'ils trouvent. En gros presque toutes les plateformes majeures sont vulnérables de PHP à Java en passant par Python puisque tout le monde ou presque utilise une variante de djb2, pour lequel il est très facile de générer des collisions. Le résultat c'est qu'on peut faire un déni de service sur à peu près n'importe quoi avec très peu de données. Avec 2 MB de données ils arrivent à occuper un processeur pendant plus d'une demi-heure.</p>
<p>Le benchmark suivant compare la courbe précédente avec une où toutes les clés se retrouvent dans la même case car on génère spécialement les clés pour que DJBX31A retourne toujours la même valeur bien que les chaînes soient différentes.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f31355f312e706e673f7261773d74727565/JEP_180_analysis_15_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_15_1.png?raw=true"></p>
<p>Comme on peut le voir l'effet est plutôt dramatique. Chaque insertion dépend donc maintenant du nombre d'éléments dans la table de hachage. Si vous vous rappelez du code de la méthode <em>put()</em>, nous avons à parcourir tous les éléments à chaque fois. Puisque nous allons insérer un nouvel élément, il faut vérifier tous les autres. La courbe devient donc quadratique. Pour 20 000 éléments on peut voir que l'on est déjà 1000 fois plus lent. Vous pouvez facilement extrapoler pour 50 000 ou 100 000.</p>
<h2 id="java-7u6--alternative-string-hashing">Java 7u6 & « alternative string-hashing »</h2>
<p>Comme la plupart des plateformes impactées par cette découverte, Java cherche une solution. Et beaucoup vont choisir une solution similaire. L'idée est qu'il faut empêcher un utilisateur de pouvoir générer des collisions. Une solution est d'utiliser des fonctions de hachage cryptographiques qui sont conçues pour cela. En pratique ce n'est pas possible car elles sont beaucoup trop lentes (grossièrement il y a au minimum un ordre de grandeur d'écart). Le consensus est alors de migrer vers une autre fonction de hachage: <a href="http://en.wikipedia.org/wiki/MurmurHash">Murmur</a> 2 ou 3. Murmur est une bonne fonction de hachage non cryptographique, elle est rapide et fournit de bons résultats. En plus on peut l'initialiser avec une graine qui va conditionner la valeur de sortie. L'idée est donc de générer la graine à l'exécution. Il devient alors compliqué pour l'utilisateur de générer des collisions car il a besoin de la graine et qu'il n'y a pas accès.</p>
<p>Python utilise cette solution et décide de <a href="http://bugs.python.org/issue13703">changer sa fonction de hachage pour Murmur</a>.</p>
<p>Java veut faire de même mais a un problème supplémentaire. La Javadoc de la méthode <code>hashCode</code> de String documente l'implémentation sous-jacente:</p>
<pre><code class="java"> <span class="cm">/**</span>
<span class="cm"> * Returns a hash code for this string. The hash code for a</span>
<span class="cm"> * <code>String</code> object is computed as</span>
<span class="cm"> * <blockquote><pre></span>
<span class="cm"> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]</span>
<span class="cm"> * </pre></blockquote></span>
<span class="cm"> * using <code>int</code> arithmetic, where <code>s[i]</code> is the</span>
<span class="cm"> * <i>i</i>th character of the string, <code>n</code> is the length of</span>
<span class="cm"> * the string, and <code>^</code> indicates exponentiation.</span>
<span class="cm"> * (The hash value of the empty string is zero.)</span>
<span class="cm"> *</span>
<span class="cm"> * @return a hash code value for this object.</span>
<span class="cm"> */</span></code></pre>
<p>DJBX31A fait donc partie du contrat de la classe, et on ne peut pas le changer sans risque de casser la compatibilité et le comportement des applications. C'est une règle stricte du côté de Java.</p>
<p>Pour cette raison on imagine donc ce qui est pour moi l'un des patchs les plus dégueulasses de l'histoire du JDK qui a été livré en Java <a href="http://www.oracle.com/technetwork/java/javase/7u6-relnotes-1729681.html">7u6</a>. En gros on ne touche à rien de ce qui existe. On rajoute une nouvelle méthode <code>hash32</code> à la classe String qui repose sur Murmur.</p>
<pre><code class="java"> <span class="kt">int</span> <span class="nf">hash32</span><span class="o">()</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">h</span> <span class="o">=</span> <span class="n">hash32</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="mi">0</span> <span class="o">==</span> <span class="n">h</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// harmless data race on hash32 here.</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">sun</span><span class="o">.</span><span class="na">misc</span><span class="o">.</span><span class="na">Hashing</span><span class="o">.</span><span class="na">murmur3_32</span><span class="o">(</span><span class="n">HASHING_SEED</span><span class="o">,</span> <span class="n">value</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span>
<span class="n">value</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
<span class="c1">// ensure result is not zero to avoid recalcing</span>
<span class="n">h</span> <span class="o">=</span> <span class="o">(</span><span class="mi">0</span> <span class="o">!=</span> <span class="n">h</span><span class="o">)</span> <span class="o">?</span> <span class="n">h</span> <span class="o">:</span> <span class="mi">1</span><span class="o">;</span>
<span class="n">hash32</span> <span class="o">=</span> <span class="n">h</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">h</span><span class="o">;</span>
<span class="o">}</span></code></pre>
<p>Maintenant on patche les collections utilisant des fonctions de hachage pour faire la chose suivante : on regarde le type de l'élément, si c'est String alors on invoque <code>hash32</code> par une introspection dédiée car la méthode n'est pas publique, sinon on invoque <code>hashCode</code>. Seulement les String sont immutables, et la valeur de <code>hashCode</code> était cachée pour éviter de la recalculer à chaque fois. On doit donc faire de même avec <code>hash32</code> qui impose donc 4 octets supplémentaire à chaque instance de String. Pour finir on initialise <code>HASHING_SEED</code> dynamiquement à l'initialisation pour empêcher les collisions.</p>
<p>C'est cool on n'a pas touché à <code>hashCode</code> ! Seulement voilà le comportement des applications peut toujours changer même en remplaçant la fonction de hachage uniquement dans les collections. Alors on rajoute un flag pour décider si on veut oui ou non utiliser le <em>alternative string-hash</em> dans les collections.</p>
<p>Voir <a href="http://permalink.gmane.org/gmane.comp.java.openjdk.core-%20libs.devel/10361">le courriel</a> sur la liste de discussion d'OpenJDK ainsi que le <a href="http://cr.openjdk.java.net/%7Emduigou/althashing7/8/webrev/">patch</a>.</p>
<p>Voilà ça pique les yeux mais ça fait le job ! Refaisons tourner le même benchmark avec Java 7u55:</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f31395f312e706e673f7261773d74727565/JEP_180_analysis_19_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_19_1.png?raw=true"></p>
<p>Ah oui j'ai dit qu'il y avait une option pour <em>l'alternative string-hashing</em> mais j'ai pas dit qu'elle était activée par défaut… Recommençons avec <code>-Djdk.map.althashing.threshold=1</code></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f32315f312e706e673f7261773d74727565/JEP_180_analysis_21_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_21_1.png?raw=true"></p>
<p>C'est mieux non ? Bon OK par défaut on est toujours vulnérable trois ans après…</p>
<h2 id="attaques-par-la-complexité-bis">Attaques par la complexité (bis)</h2>
<p>Seulement voilà, entre temps quelques-uns ont commencé à creuser le problème. Ils ont attaqué Murmur3 avec graine qui n'a pas <a href="http://www.eng.tau.ac.il/%7Eyash/C2_039_Wool.pdf">tenu</a> très longtemps. Ca a d'ailleurs été <a href="http://www.youtube.com/watch?v=wGYj8fhhUVA">présenté au 29c3</a>. Dans les speakers on notera DJB, oui c'est le même.</p>
<p>Rebelote, tous ceux qui sont passés à Murmur sont impactés ainsi que quelques copains dont les fonctions ont aussi été cassées. C'est un peu moins trivial de générer des collisions avec Murmur mais le travail difficile a été fait pour nous. On n'a qu'à écrire le code…</p>
<p>Essayons de refaire tourner notre benchmark en générant des collisions contre Murmur:</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f32355f312e706e673f7261773d74727565/JEP_180_analysis_25_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_25_1.png?raw=true"></p>
<p>Cette fois nous comparons le comportement usuel avec:</p>
<ul>
<li>Des collisions contre DJBX31A sans <em>l'alternative string-hashing</em>
</li>
<li>Des collisions contre Murmur3 avec <em>l'alternative string-hashing</em>
</li>
</ul><p>(Je n'ai pas investigué les deux points à 15k et 25k qui sont très étranges. Le générateur passe les tests unitaires et les résultats eux sont stables…)</p>
<p>C'est grosso modo la même chose. On a donc fait un patch moche qui ne sert plus à rien puisque dans les deux cas on est vulnérable…</p>
<h2 id="jep-180-une-solution-intéressante">JEP 180: Une solution intéressante</h2>
<p>Maintenant qu'est-ce qu'on fait ?</p>
<p>En même temps qu'ils ont cassé Murmur avec graine, DJB et ses potes ont proposé une nouvelle fonction de hachage: <a href="http://en.wikipedia.org/wiki/SipHash">SipHash</a>. Elle est vendue comme étant aussi rapide que les précédentes mais résistante aux attaques par collisions.</p>
<p>La plupart des plateformes ont migré vers SipHash, Python par exemple. Et comme on s'est déjà fait avoir une fois on en profite pour faire la <a href="http://legacy.python.org/dev/peps/pep-0456/">PEP 456</a> qui permet d'avoir des fonctions de hash interchangeable pour les chaîne de caractères et tableaux d'octets. On bascule à SipHash mais comme on sait que ça risque de recommencer, on prévoit le coup…</p>
<p>Du côté de Java on a toujours le même problème avec <code>hashCode</code>, rechanger hash32 fait prendre quelques risques aussi et le patch initial étant "crado" on aimerait bien s'en débarrasser. On choisit donc une approche radicalement différente. Plutôt que de chercher une fonction de hachage parfaite, on rebascule sur DJBX31A. On s'applique plutôt à résoudre le problème du <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48L2RlZnM+PGcgc3Ryb2tlPSJibGFjayIgZmlsbD0iYmxh%0AY2siIHN0cm9rZS13aWR0aD0iMCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAg%0ALTEgMCAwKSI+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU5JLTRGIiB4bGluazpo%0AcmVmPSIjU1RJWFdFQk1BSU5JLTRGIj48L3VzZT48dXNlIGhyZWY9IiNTVElY%0AV0VCTUFJTi0yOCIgeD0iNzI3IiB5PSIwIiB4bGluazpocmVmPSIjU1RJWFdF%0AQk1BSU4tMjgiPjwvdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RSIg%0AeD0iMTA2NSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RSI+%0APC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU4tMjkiIHg9IjE1NzAiIHk9%0AIjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTi0yOSI+PC91c2U+PC9nPjwv%0Ac3ZnPg==%0A" alt="O(n)"> au pire cas. Le <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48L2RlZnM+PGcgc3Ryb2tlPSJibGFjayIgZmlsbD0iYmxh%0AY2siIHN0cm9rZS13aWR0aD0iMCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAg%0ALTEgMCAwKSI+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU5JLTRGIiB4bGluazpo%0AcmVmPSIjU1RJWFdFQk1BSU5JLTRGIj48L3VzZT48dXNlIGhyZWY9IiNTVElY%0AV0VCTUFJTi0yOCIgeD0iNzI3IiB5PSIwIiB4bGluazpocmVmPSIjU1RJWFdF%0AQk1BSU4tMjgiPjwvdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RSIg%0AeD0iMTA2NSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RSI+%0APC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1BSU4tMjkiIHg9IjE1NzAiIHk9%0AIjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTi0yOSI+PC91c2U+PC9nPjwv%0Ac3ZnPg==%0A" alt="O(n)"> vient du fait que les collisions sont gérées avec une liste chaînée. Si on utilise un arbre balancé plutôt qu'une liste on passe en <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA5ZXg7IGhlaWdodDogMi4xNDNleDsgdmVydGlj%0AYWwtYWxpZ246IC0wLjU3MWV4OyBtYXJnaW4tdG9wOiAxcHg7IG1hcmdpbi1y%0AaWdodDogMHB4OyBtYXJnaW4tYm90dG9tOiAxcHg7IG1hcmdpbi1sZWZ0OiAw%0AcHg7IHBvc2l0aW9uOiBzdGF0aWM7ICIgdmlld0JveD0iMCAtNzA5LjI1ODEy%0AMzI1NTE1NDkgMzg3OCA5NDEuNTE2MjQ2NTEwMzEiIHhtbG5zPSJodHRwOi8v%0Ad3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnMgaWQ9Ik1hdGhKYXhfU1ZHX2ds%0AeXBocyI+PHBhdGggaWQ9IlNUSVhXRUJNQUlOSS00RiIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTY5OSA0MThjMCAtMTQ2IC04OCAtMjg1IC0yMDcgLTM2NWMt%0ANjUgLTQ0IC0xNDAgLTcxIC0yMTQgLTcxYy0xMzAgMCAtMjE4IDg1IC0yMTgg%0AMjM0YzAgMTIyIDczIDI2MiAxNzcgMzUzYzY5IDYwIDE1MiA5NyAyMzcgOTdj%0AMTQ0IDEgMjI1IC05NiAyMjUgLTI0OHpNNTk0IDQ4MWMwIDk0IC00OSAxNTIg%0ALTEyOSAxNTJjLTc0IDAgLTEzNyAtNTEgLTE4NiAtMTE3Yy03MyAtOTkgLTEx%0ANCAtMjMyIC0xMTQgLTMzMiBjMCAtMTA5IDQ2IC0xNjkgMTMwIC0xNjljNjcg%0AMCAxMjQgMzkgMTcwIDk1Yzg0IDEwNCAxMjkgMjY5IDEyOSAzNzFaIj48L3Bh%0AdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlOLTI4IiBzdHJva2Utd2lkdGg9IjEw%0AIiBkPSJNMzA0IC0xNjFsLTEyIC0xNmMtMTU4IDkwIC0yNDQgMjU5IC0yNDQg%0ANDI5YzAgMTg1IDg3IDMyOSAyNDcgNDI0bDkgLTE2Yy0xMzkgLTExOSAtMTcw%0AIC0yMTIgLTE3MCAtNDA1YzAgLTE4NiAzMCAtMjk5IDE3MCAtNDE2WiI+PC9w%0AYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNkMiIHN0cm9rZS13aWR0aD0i%0AMTAiIGQ9Ik0yNzkgNjc4bC0xNTMgLTU4NWMtNSAtMTggLTggLTM1IC04IC00%0AM2MwIC0xMiA3IC0xOCAxNyAtMThjMTUgMCAzOCAxNiA2NyA1N2wyNSAzNWwx%0ANCAtMTBjLTYwIC05NSAtOTcgLTEyNSAtMTUxIC0xMjVjLTMyIDAgLTQ5IDE5%0AIC00OSA1NmMwIDggMSAyMCA0IDMwbDEzNyA1MjRjMyAxMCAzIDE2IDMgMTlj%0AMCAxMiAtMTcgMjIgLTQ5IDIyaC0xOHYxNmM1OSA3IDk2IDE0IDE1NSAyN1oi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZGIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDY4IDMwMWMwIC03NiAtNDAgLTE2NCAtMTA2IC0yMjlj%0ALTU4IC01OCAtMTIyIC04MyAtMTg4IC04M2MtOTQgMCAtMTQ3IDUyIC0xNDcg%0AMTM5YzAgMTEyIDc1IDIyNyAxODAgMjgzYzM5IDIxIDc5IDMwIDEyMCAzMGM4%0AMSAwIDE0MSAtNTIgMTQxIC0xNDB6TTM4NCAzMjZjMCA2MSAtMjggOTQgLTcx%0AIDk0Yy00NCAwIC04OCAtMzEgLTEyOCAtOTFjLTQ2IC03MCAtNzQgLTE0OSAt%0ANzQgLTIyOGMwIC02MCAzMSAtOTEgNzggLTkxIGM0NCAwIDgyIDI5IDEyMSA4%0AM2M0NiA2MyA3NCAxNTcgNzQgMjMzWiI+PC9wYXRoPjxwYXRoIGlkPSJTVElY%0AV0VCTUFJTkktNjciIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik00NzEgMzY2aC00%0AOWM5IC0xOCA5IC0zNCA5IC01MWMwIC04NCAtOTIgLTE2NCAtMTg1IC0xNjRj%0ALTExIDAgLTIyIDEgLTMxIDNjLTMgMSAtNSAxIC03IDFjLTE3IDAgLTM2IC0y%0AMCAtMzYgLTQxYzAgLTE4IDI3IC0zMSA3MSAtNDJjOTYgLTIzIDE0MiAtNjcg%0AMTQyIC0xMjdjMCAtODcgLTc3IC0xNTEgLTIxMCAtMTUxYy0xMDIgMCAtMTY3%0AIDM2IC0xNjcgMTA4YzAgNTEgMTkgNzggMTE3IDEzN2MtMTggMTEgLTI3IDI2%0AIC0yNyAzOSBjMCAyOSAyMyA1OSA3NyA4NGMtNTYgMjAgLTc5IDU2IC03OSAx%0AMDhjMCAxMDIgMTAwIDE3MSAyMDEgMTcxYzM4IDAgNzEgLTkgOTggLTI4Yzgg%0ALTYgMTMgLTggMTYgLThoNjB2LTM5ek0zNTIgMzQ4YzAgNTMgLTE5IDcxIC01%0ANiA3MWMtNjIgMCAtMTIyIC03MyAtMTIyIC0xNzJjMCAtNDcgMjIgLTc1IDYw%0AIC03NWMzNCAwIDYxIDE4IDg1IDU5YzIwIDM0IDMzIDc1IDMzIDExN3pNMzI1%0AIC05MGMwIDQ2IC0zNiA3NCAtMTQzIDEwNyBjLTEzIDQgLTIzIDcgLTM0IDEx%0AYy05IDAgLTUxIC0zNCAtNjUgLTUyYy0xNSAtMTkgLTIwIC0zNSAtMjAgLTU4%0AYzAgLTcwIDQ3IC0xMDIgMTI3IC0xMDJjODEgMCAxMzUgNDMgMTM1IDk0WiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTkktNkMiIHg9IjEw%0ANjUiIHk9IjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNkMiPjwvdXNl%0APjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RiIgeD0iMTM0OSIgeT0iMCIg%0AeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RiI+PC91c2U+PHVzZSBocmVm%0APSIjU1RJWFdFQk1BSU5JLTY3IiB4PSIxODU0IiB5PSIwIiB4bGluazpocmVm%0APSIjU1RJWFdFQk1BSU5JLTY3Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VC%0ATUFJTi0yOCIgeD0iMjM1OSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJN%0AQUlOLTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTkktNkUiIHg9%0AIjI2OTciIHk9IjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNkUiPjwv%0AdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOLTI5IiB4PSIzMjAyIiB5PSIw%0AIiB4bGluazpocmVmPSIjU1RJWFdFQk1BSU4tMjkiPjwvdXNlPjx1c2UgaHJl%0AZj0iI1NUSVhXRUJNQUlOLTI5IiB4PSIzNTQwIiB5PSIwIiB4bGluazpocmVm%0APSIjU1RJWFdFQk1BSU4tMjkiPjwvdXNlPjwvZz48L3N2Zz4=%0A" alt="O(log(n))"> ce qui réduit drastiquement le problème.</p>
<p>C'est ce que propose la <a href="http://openjdk.java.net/jeps/180">JEP 180</a> et qui a été implémenté dans OpenJDK 8.</p>
<p>Refaisons tourner notre benchmark sur OpenJDK 8:</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f32395f312e706e673f7261773d74727565/JEP_180_analysis_29_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_29_1.png?raw=true"></p>
<p>Cette fois ci nous comparons le comportement normal d'OpenJDK 8 et Java 7u55 ainsi que le comportement d'OpenJDK8 avec des collisions.</p>
<p>Tout d'abord nous constatons que les performances dans le cas normal n'ont pas régressé. Ensuite nous voyons que contrairement à une solution qui vise a prévenir entièrement les collisions, l'utilisation d'arbre balancé a tout de même un coût. Les opérations passent de <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA0LjQyOWV4OyBoZWlnaHQ6IDIuMTQzZXg7IHZl%0AcnRpY2FsLWFsaWduOiAtMC41NzFleDsgbWFyZ2luLXRvcDogMXB4OyBtYXJn%0AaW4tcmlnaHQ6IDBweDsgbWFyZ2luLWJvdHRvbTogMXB4OyBtYXJnaW4tbGVm%0AdDogMHB4OyBwb3NpdGlvbjogc3RhdGljOyAiIHZpZXdCb3g9IjAgLTcwMi4y%0ANTgxMjMyNTUxNTQ5IDE5MDggOTA1LjUxNjI0NjUxMDMxIiB4bWxucz0iaHR0%0AcDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NW%0AR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEYiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik02OTkgNDE4YzAgLTE0NiAtODggLTI4NSAtMjA3IC0z%0ANjVjLTY1IC00NCAtMTQwIC03MSAtMjE0IC03MWMtMTMwIDAgLTIxOCA4NSAt%0AMjE4IDIzNGMwIDEyMiA3MyAyNjIgMTc3IDM1M2M2OSA2MCAxNTIgOTcgMjM3%0AIDk3YzE0NCAxIDIyNSAtOTYgMjI1IC0yNDh6TTU5NCA0ODFjMCA5NCAtNDkg%0AMTUyIC0xMjkgMTUyYy03NCAwIC0xMzcgLTUxIC0xODYgLTExN2MtNzMgLTk5%0AIC0xMTQgLTIzMiAtMTE0IC0zMzIgYzAgLTEwOSA0NiAtMTY5IDEzMCAtMTY5%0AYzY3IDAgMTI0IDM5IDE3MCA5NWM4NCAxMDQgMTI5IDI2OSAxMjkgMzcxWiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMzEiIHN0cm9rZS13aWR0%0AaD0iMTAiIGQ9Ik0zOTQgMGgtMjc2djE1Yzc0IDQgOTUgMjUgOTUgODB2NDQ5%0AYzAgMzQgLTkgNDkgLTMwIDQ5Yy0xMCAwIC0yNyAtNSAtNDUgLTEybC0yNyAt%0AMTB2MTRsMTc5IDkxbDkgLTN2LTU5N2MwIC00MyAyMCAtNjEgOTUgLTYxdi0x%0ANVoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTi0zMSIgeD0iMTA2%0ANSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTMxIj48L3VzZT48%0AdXNlIGhyZWY9IiNTVElYV0VCTUFJTi0yOSIgeD0iMTU3MCIgeT0iMCIgeGxp%0Abms6aHJlZj0iI1NUSVhXRUJNQUlOLTI5Ij48L3VzZT48L2c+PC9zdmc+%0A" alt="O(1)"> à <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgc3R5bGU9IndpZHRoOiA5ZXg7IGhlaWdodDogMi4xNDNleDsgdmVydGlj%0AYWwtYWxpZ246IC0wLjU3MWV4OyBtYXJnaW4tdG9wOiAxcHg7IG1hcmdpbi1y%0AaWdodDogMHB4OyBtYXJnaW4tYm90dG9tOiAxcHg7IG1hcmdpbi1sZWZ0OiAw%0AcHg7IHBvc2l0aW9uOiBzdGF0aWM7ICIgdmlld0JveD0iMCAtNzA5LjI1ODEy%0AMzI1NTE1NDkgMzg3OCA5NDEuNTE2MjQ2NTEwMzEiIHhtbG5zPSJodHRwOi8v%0Ad3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnMgaWQ9Ik1hdGhKYXhfU1ZHX2ds%0AeXBocyI+PHBhdGggaWQ9IlNUSVhXRUJNQUlOSS00RiIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTY5OSA0MThjMCAtMTQ2IC04OCAtMjg1IC0yMDcgLTM2NWMt%0ANjUgLTQ0IC0xNDAgLTcxIC0yMTQgLTcxYy0xMzAgMCAtMjE4IDg1IC0yMTgg%0AMjM0YzAgMTIyIDczIDI2MiAxNzcgMzUzYzY5IDYwIDE1MiA5NyAyMzcgOTdj%0AMTQ0IDEgMjI1IC05NiAyMjUgLTI0OHpNNTk0IDQ4MWMwIDk0IC00OSAxNTIg%0ALTEyOSAxNTJjLTc0IDAgLTEzNyAtNTEgLTE4NiAtMTE3Yy03MyAtOTkgLTEx%0ANCAtMjMyIC0xMTQgLTMzMiBjMCAtMTA5IDQ2IC0xNjkgMTMwIC0xNjljNjcg%0AMCAxMjQgMzkgMTcwIDk1Yzg0IDEwNCAxMjkgMjY5IDEyOSAzNzFaIj48L3Bh%0AdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlOLTI4IiBzdHJva2Utd2lkdGg9IjEw%0AIiBkPSJNMzA0IC0xNjFsLTEyIC0xNmMtMTU4IDkwIC0yNDQgMjU5IC0yNDQg%0ANDI5YzAgMTg1IDg3IDMyOSAyNDcgNDI0bDkgLTE2Yy0xMzkgLTExOSAtMTcw%0AIC0yMTIgLTE3MCAtNDA1YzAgLTE4NiAzMCAtMjk5IDE3MCAtNDE2WiI+PC9w%0AYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNkMiIHN0cm9rZS13aWR0aD0i%0AMTAiIGQ9Ik0yNzkgNjc4bC0xNTMgLTU4NWMtNSAtMTggLTggLTM1IC04IC00%0AM2MwIC0xMiA3IC0xOCAxNyAtMThjMTUgMCAzOCAxNiA2NyA1N2wyNSAzNWwx%0ANCAtMTBjLTYwIC05NSAtOTcgLTEyNSAtMTUxIC0xMjVjLTMyIDAgLTQ5IDE5%0AIC00OSA1NmMwIDggMSAyMCA0IDMwbDEzNyA1MjRjMyAxMCAzIDE2IDMgMTlj%0AMCAxMiAtMTcgMjIgLTQ5IDIyaC0xOHYxNmM1OSA3IDk2IDE0IDE1NSAyN1oi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZGIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDY4IDMwMWMwIC03NiAtNDAgLTE2NCAtMTA2IC0yMjlj%0ALTU4IC01OCAtMTIyIC04MyAtMTg4IC04M2MtOTQgMCAtMTQ3IDUyIC0xNDcg%0AMTM5YzAgMTEyIDc1IDIyNyAxODAgMjgzYzM5IDIxIDc5IDMwIDEyMCAzMGM4%0AMSAwIDE0MSAtNTIgMTQxIC0xNDB6TTM4NCAzMjZjMCA2MSAtMjggOTQgLTcx%0AIDk0Yy00NCAwIC04OCAtMzEgLTEyOCAtOTFjLTQ2IC03MCAtNzQgLTE0OSAt%0ANzQgLTIyOGMwIC02MCAzMSAtOTEgNzggLTkxIGM0NCAwIDgyIDI5IDEyMSA4%0AM2M0NiA2MyA3NCAxNTcgNzQgMjMzWiI+PC9wYXRoPjxwYXRoIGlkPSJTVElY%0AV0VCTUFJTkktNjciIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik00NzEgMzY2aC00%0AOWM5IC0xOCA5IC0zNCA5IC01MWMwIC04NCAtOTIgLTE2NCAtMTg1IC0xNjRj%0ALTExIDAgLTIyIDEgLTMxIDNjLTMgMSAtNSAxIC03IDFjLTE3IDAgLTM2IC0y%0AMCAtMzYgLTQxYzAgLTE4IDI3IC0zMSA3MSAtNDJjOTYgLTIzIDE0MiAtNjcg%0AMTQyIC0xMjdjMCAtODcgLTc3IC0xNTEgLTIxMCAtMTUxYy0xMDIgMCAtMTY3%0AIDM2IC0xNjcgMTA4YzAgNTEgMTkgNzggMTE3IDEzN2MtMTggMTEgLTI3IDI2%0AIC0yNyAzOSBjMCAyOSAyMyA1OSA3NyA4NGMtNTYgMjAgLTc5IDU2IC03OSAx%0AMDhjMCAxMDIgMTAwIDE3MSAyMDEgMTcxYzM4IDAgNzEgLTkgOTggLTI4Yzgg%0ALTYgMTMgLTggMTYgLThoNjB2LTM5ek0zNTIgMzQ4YzAgNTMgLTE5IDcxIC01%0ANiA3MWMtNjIgMCAtMTIyIC03MyAtMTIyIC0xNzJjMCAtNDcgMjIgLTc1IDYw%0AIC03NWMzNCAwIDYxIDE4IDg1IDU5YzIwIDM0IDMzIDc1IDMzIDExN3pNMzI1%0AIC05MGMwIDQ2IC0zNiA3NCAtMTQzIDEwNyBjLTEzIDQgLTIzIDcgLTM0IDEx%0AYy05IDAgLTUxIC0zNCAtNjUgLTUyYy0xNSAtMTkgLTIwIC0zNSAtMjAgLTU4%0AYzAgLTcwIDQ3IC0xMDIgMTI3IC0xMDJjODEgMCAxMzUgNDMgMTM1IDk0WiI+%0APC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOCIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTMwNCAtMTYxbC0xMiAtMTZjLTE1OCA5MCAtMjQ0IDI1OSAt%0AMjQ0IDQyOWMwIDE4NSA4NyAzMjkgMjQ3IDQyNGw5IC0xNmMtMTM5IC0xMTkg%0ALTE3MCAtMjEyIC0xNzAgLTQwNWMwIC0xODYgMzAgLTI5OSAxNzAgLTQxNloi%0APjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTZFIiBzdHJva2Utd2lk%0AdGg9IjEwIiBkPSJNNDYwIDExN2wxNCAtMTNjLTY4IC05MyAtOTMgLTExMyAt%0AMTQwIC0xMTNjLTI1IDAgLTQ3IDE2IC00NyA1NGMwIDEwIDIgMjMgMTYgNzVs%0ANDQgMTYyYzggMzEgMTQgNjcgMTQgNzljMCAxOCAtOSAyOSAtMjQgMjljLTQw%0AIDAgLTg1IC00OSAtMTQ4IC0xNDJjLTQ1IC02NyAtNTMgLTkwIC0xMDAgLTI0%0AOGgtNzVsOTYgMzUwYzEgNSAyIDExIDIgMTdjMCAyMCAtMTQgMjYgLTY1IDI3%0AdjE2YzgxIDE2IDEwOSAyMCAxNjIgMzFsNCAtMmwtNjcgLTIxOCBjMTAwIDE2%0AMCAxNjcgMjIwIDIzMSAyMjBjNDMgMCA2NSAtMjUgNjUgLTYxYzAgLTE4IC00%0AIC0zOSAtMTAgLTYwbC01NiAtMjAzYy0xMCAtMzYgLTE0IC01MyAtMTQgLTYx%0AYzAgLTkgNCAtMTggMTYgLTE4YzE0IDAgMzIgMTYgNjEgNTNjNyA4IDE0IDE3%0AIDIxIDI2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTi0yOSIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTI5IDY2MGwxMiAxNmMxNTMgLTkyIDI0NCAt%0AMjU5IDI0NCAtNDI5YzAgLTE4NSAtODggLTMyNyAtMjQ3IC00MjRsLTkgMTZj%0AMTQyIDExNyAxNzAgMjExIDE3MCA0MDVjMCAxODcgLTI1IDMwMiAtMTcwIDQx%0ANloiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tMjkiIHN0cm9rZS13%0AaWR0aD0iMTAiIGQ9Ik0yOSA2NjBsMTIgMTZjMTUzIC05MiAyNDQgLTI1OSAy%0ANDQgLTQyOWMwIC0xODUgLTg4IC0zMjcgLTI0NyAtNDI0bC05IDE2YzE0MiAx%0AMTcgMTcwIDIxMSAxNzAgNDA1YzAgMTg3IC0yNSAzMDIgLTE3MCA0MTZaIj48%0AL3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9ImJsYWNrIiBz%0AdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAg%0AMCkiPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS00RiIgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS00RiI+PC91c2U+PHVzZSBocmVmPSIjU1RJWFdFQk1B%0ASU4tMjgiIHg9IjcyNyIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlO%0ALTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTkktNkMiIHg9IjEw%0ANjUiIHk9IjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNkMiPjwvdXNl%0APjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOSS02RiIgeD0iMTM0OSIgeT0iMCIg%0AeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02RiI+PC91c2U+PHVzZSBocmVm%0APSIjU1RJWFdFQk1BSU5JLTY3IiB4PSIxODU0IiB5PSIwIiB4bGluazpocmVm%0APSIjU1RJWFdFQk1BSU5JLTY3Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VC%0ATUFJTi0yOCIgeD0iMjM1OSIgeT0iMCIgeGxpbms6aHJlZj0iI1NUSVhXRUJN%0AQUlOLTI4Ij48L3VzZT48dXNlIGhyZWY9IiNTVElYV0VCTUFJTkktNkUiIHg9%0AIjI2OTciIHk9IjAiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNkUiPjwv%0AdXNlPjx1c2UgaHJlZj0iI1NUSVhXRUJNQUlOLTI5IiB4PSIzMjAyIiB5PSIw%0AIiB4bGluazpocmVmPSIjU1RJWFdFQk1BSU4tMjkiPjwvdXNlPjx1c2UgaHJl%0AZj0iI1NUSVhXRUJNQUlOLTI5IiB4PSIzNTQwIiB5PSIwIiB4bGluazpocmVm%0APSIjU1RJWFdFQk1BSU4tMjkiPjwvdXNlPjwvZz48L3N2Zz4=%0A" alt="O(log(n))">. Cependant si on regarde les chiffres ce n'est pas dramatique. À 20 000 éléments nous sommes maintenant à ~10ms plutôt que ~1ms loin de la seconde initiale.</p>
<p>Nous avons regardé le point de vue performance, cependant utiliser des arbres balancés a aussi un impact non négligeable sur la consommation mémoire. En effet au lieu d'avoir à stocker un bête pointeur sur l'élément suivant, on se retrouve avec quatre pointeurs et un booléen. Ce qui pourrait faire exploser la consommation mémoire. Cependant par défaut on utilise toujours une liste chaînée. Quand le nombre de collisions augmente dans une case et dépasse un seuil on convertit tout ou une partie de la liste en arbre balancé pour optimiser le ratio consommation mémoire/performance. Cette technique est appliquée à chaque feuille de l'arbre. On démarre avec une liste, puis on convertit la feuille en arbre quand elle devient trop grande. Quand on supprime des éléments on peut rebasculer vers une liste chaînée. Les seuils de conversion étant respectivement à 8 et 6 éléments.</p>
<p>Si l'on observe la consommation mémoire avec <a href="http://openjdk.java.net/projects/code-tools/jol/">Jol</a> on peut voir que ça marche très bien:</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f756e706f7274616e742d74686f75676874732f3230313430355f4a45505f3138302f6d61737465722f4a45505f3138305f616e616c797369735f66696c65732f4a45505f3138305f616e616c797369735f33315f312e706e673f7261773d74727565/JEP_180_analysis_31_1.png?raw=true" alt="png" title="Source : https://raw.githubusercontent.com/unportant-thoughts/201405_JEP_180/master/JEP_180_analysis_files/JEP_180_analysis_31_1.png?raw=true"></p>
<p>Ici on a fait attention à ce que les chaînes aient toujours la même taille dans les deux cas.</p>
<p>En pratique dans une utilisation courante avec une fonction de hachage correcte, les collisions seront rares et les arbres balancés ne seront jamais utilisés. Par contre quand ils rentrent en action cela permet d'éviter les DOS ou simplement d'avoir de bonnes performances quand la fonction <code>hashCode</code> de l'utilisateur est biaisée.</p>
<p>J'invite le lecteur intéressé à aller regarder <a href="http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/HashMap.java#l38">le code</a>. Le commentaire initial explique extrêmement clairement comment ça fonctionne et c'est plutôt rigolo à lire.</p>
<h3 id="conclusion">Conclusion</h3>
<p>L'approche d'OpenJDK 8 est intéressante et différente des autres plateformes puisqu'elle ne cherche pas à résoudre le problème des collisions mais à améliorer le pire cas. Changer de fonction de hachage pour les String étant compliqué on peut comprendre ce choix. Ils ont fait le pari que les performances offertes par les arbres balancés suffiront à se protéger et à offrir une bonne robustesse aux mauvaises fonctions de hachage. En pratique, au pire cas on observe un ralentissement constant de ~10x quelle que soit la taille de la collection.</p>
<p>De l'autre côté beaucoup de plateformes ont changé de fonction de hachage pour éviter le pire cas mais n'ont pas cherché à l'améliorer et sont restés aux listes chainées. Ils se protègent donc des dénis de service selon les connaissances actuelles mais ne cherchent pas à se protéger pour le futur ni à offrir une réponse performante aux fonctions de hachage qui pourraient être légèrement biaisées pour certains autres types de données car implémentées par l'utilisateur.</p>
<p>Dans l'idéal les deux techniques devraient être appliquées mais je ne connais pas de plateforme qui le fasse. Et vous les outils que vous utilisez ils ont fait quoi ?</p>
<p>Voilà c'est un problème pas nouveau mais on en entendra certainement à nouveau parler. Dès qu'on lit une valeur du monde extérieur, celui-ci va s'arranger pour trouver un moyen de faire des choses "sympas". Les attaques algorithmiques permettent de varier un peu les plaisirs et forcent à s'interroger longuement à chaque fois qu'on stock une valeur que l'on ne contrôle pas.</p>
<p>Note: Tout le matériel créé pour écrire l'article est <a href="https://github.com/unportant-thoughts/201405_JEP_180">en ligne</a>.</p>
<p><abbr title="Note des modérateurs">NdM</abbr> : <em>Pour ceux qui se demandent comment sont fait les graphiques, ils s'agit du mode xkcd de matplotlib comme expliqué par <a href="//linuxfr.org/users/cykl/journaux/openjdk-jep-180-hashmap-collisions-attaques-par-la-complexite#comment-1536363">l'auteur dans les commentaires du journal à l'origine de la dépêche</a>.</em></p></div><div><a href="https://linuxfr.org/news/openjdk-jep-180-hashmap-collisions-attaques-par-la-complexite.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/102082/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/openjdk-jep-180-hashmap-collisions-attaques-par-la-complexite#comments">ouvrir dans le navigateur</a>
</p>
ckylclaudexpalm123Benoît SibaudNils RatusznikZeroHeurehttps://linuxfr.org/nodes/102082/comments.atomtag:linuxfr.org,2005:News/352402014-04-02T20:48:58+02:002014-04-03T16:09:50+02:00OpenJDK 8, JEP 142 & False SharingLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Java 8 est sorti ce mois‐ci et vous avez même eu droit à une <a href="//linuxfr.org/news/java-8-et-netbeans-8-sont-disponibles">dépêche, ici‐même, qui parle des lambdas, de l’API flux (<em>stream API</em>)</a>, etc.</p>
<p>Cependant, derrière ces gros changements qui impactent le monde hétérogène des développeurs Java, il y a des petits changements qui eux servent plutôt aux développeurs qui font des briques de base, de l’infrastructure ou du code qui va vite. Je vous propose donc d’explorer quelques <em>JDK Enhancement Proposals</em> d’OpenJDK.</p>
<p>Pour cette première dépêche, on commence avec la <a href="http://openjdk.java.net/jeps/142">JEP 142</a> : <em>Reduce Cache Contention on Specified Fields</em> soit l’annotation <code>@Contended</code> qui vise à proposer une solution aux problèmes de <a href="http://en.wikipedia.org/wiki/False_sharing"><em>false sharing</em></a>.</p>
<p><abbr title="Note des modérateurs">NdM</abbr> : <em>merci à ckyl pour son journal.</em></p></div><ul><li>lien nᵒ 1 : <a title="http://linuxfr.org/users/cykl/journaux/openjdk-8-jep-142-false-sharing" hreflang="fr" href="https://linuxfr.org/redirect/89967">Journal à l’origine de la dépêche</a></li><li>lien nᵒ 2 : <a title="https://linuxfr.org/news/java-8-et-netbeans-8-sont-disponibles" hreflang="fr" href="https://linuxfr.org/redirect/89968">LinuxFr.org : Java 8 et NetBeans 8 sont disponibles</a></li><li>lien nᵒ 3 : <a title="http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html" hreflang="en" href="https://linuxfr.org/redirect/89969">Nouveautés du JDK 8</a></li><li>lien nᵒ 4 : <a title="http://openjdk.java.net/jeps/142" hreflang="en" href="https://linuxfr.org/redirect/89970">JEP 142: Reduce Cache Contention on Specified Fields</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><ul>
<li><a href="#cest-quoi-le-false-sharing">C’est quoi le <em>false sharing</em> ?</a></li>
<li><a href="#exemple">Exemple</a></li>
<li><a href="#contended">@Contended</a></li>
<li><a href="#limitations">Limitations</a></li>
<li><a href="#comment-d%C3%A9tecter-un-cas-de-false-sharing">Comment détecter un cas de false sharing</a></li>
<li><a href="#cas-courants">Cas courants</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul></li>
</ul><h3 id="cest-quoi-le-false-sharing">C’est quoi le <em>false sharing</em> ?</h3>
<p>Le <em>false sharing</em> est un problème de performance en environnement parallèle qui est causé par une <em>« leaky abstraction »</em> du matériel. La présentation suivante est extrêmement grossière et ne vise qu’à faire comprendre le problème aux gens ne connaissant pas du tout le domaine.</p>
<p>En tant que développeur, on aime se représenter la mémoire comme un espace d’adressage continu. Plus on travaille dans un langage de haut niveau, plus cela est vrai. Par exemple, les problèmes d’alignement sont une notion totalement inconnue pour beaucoup. Cependant, dans ce monde idéal, la réalité du matériel refait surface périodiquement.</p>
<p>Un processeur étant <a href="http://www.eecs.berkeley.edu/%7Ercs/research/interactive_latency.html">beaucoup plus rapide</a> que la mémoire vive et le <a href="http://en.wikipedia.org/wiki/Locality_of_reference">principe de localité</a> ayant été découvert, il dispose de <a href="http://en.wikipedia.org/wiki/CPU_cache">caches mémoire</a>. Ce sont des petits morceaux de mémoire tampon travaillant à une vitesse beaucoup plus proche de celle du processeur. Le pari étant qu’une fois l’accès coûteux à la mémoire centrale effectué, cette valeur va être réutilisée et on ira alors la chercher dans ce cache en gagnant énormément de temps.</p>
<p>Le problème du <em>false sharing</em> vient de deux choses :</p>
<ul>
<li>L’architecture des caches. Un cache est composé d’un certain nombre de lignes de taille fixe (64 octets, par exemple). Lorsqu’une modification est faite, elle affecte la ligne entière.</li>
<li>Le processeur doit gérer la cohérence entre ces caches à l’aide d’un <a href="http://en.wikipedia.org/wiki/Cache_coherence">protocole de cohérence</a>. Il s’agit de s’assurer que lorsqu’un processeur ou un cœur fait une modification, elle sera visible par les autres. Chaque architecture a son propre modèle de cohérence, le x86 étant, par exemple, particulièrement fort. Ce modèle est exposé dans les langages de bas niveau, mais les langages de haut niveau décrivent souvent leur propre modèle mémoire. Charge au compilateur de traduire celui du langage vers celui de la plate‐forme.</li>
</ul><p>Si l’on met ces deux choses ensemble, on arrive au <em>false sharing</em> : deux variables théoriquement indépendantes se retrouvent sur la même ligne de cache. Chacune est lue ou modifiée par un processeur distinct, cependant les processeurs doivent passer leur temps à se synchroniser, et les performances s’écroulent.</p>
<p>Bref, notre bel espace mémoire uniforme vient d’en prendre un coup. Coller ou espacer deux variables peut faire varier d’un à plusieurs ordres de grandeur la performance de notre structure de données.</p>
<h3 id="exemple">Exemple</h3>
<p>Commençons avec un banc d’essai très simple : une classe avec un seul membre et quatre fils d’exécution (<em>threads</em>). Le premier lit en permanence la valeur de ce membre, les trois autres ne font rien. Le banc d’essai est écrit avec <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> :</p>
<pre><code class="java"> <span class="nd">@State</span><span class="o">(</span><span class="n">Scope</span><span class="o">.</span><span class="na">Benchmark</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">StateNoFalseSharing</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="n">readOnly</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@GenerateMicroBenchmark</span>
<span class="nd">@Group</span><span class="o">(</span><span class="s">"noFalseSharing"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">reader</span><span class="o">(</span><span class="n">StateNoFalseSharing</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span> <span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="na">readOnly</span><span class="o">;</span> <span class="o">}</span>
<span class="nd">@GenerateMicroBenchmark</span>
<span class="nd">@Group</span><span class="o">(</span><span class="s">"noFalseSharing"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">noOp</span><span class="o">(</span><span class="n">StateNoFalseSharing</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span> <span class="o">}</span></code></pre>
<p>Ce qui nous donne le résultat suivant :</p>
<pre><code>Benchmark Mode Samples Mean Mean error Units
g.c.Benchmarks.noFalseSharing:noOp avgt 18 0.297 0.002 ns/op
g.c.Benchmarks.noFalseSharing:reader avgt 18 0.743 0.003 ns/op
</code></pre>
<p>Comme on pouvait s’y attendre, c’est très rapide, et on aura du mal à mesurer quelque chose de plus petit.</p>
<p>Maintenant, faisons évoluer notre banc d’essai. Nous ajoutons un deuxième membre qui va être accédé par les trois fils d’exécution qui ne faisaient rien. Le premier fil ne change absolument pas et, si les caches n’étaient pas organisés en ligne, il n’y aurait aucune raison que sa performance soit affectée.</p>
<pre><code class="java"> <span class="nd">@State</span><span class="o">(</span><span class="n">Scope</span><span class="o">.</span><span class="na">Group</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">StateFalseSharing</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">readOnly</span><span class="o">;</span>
<span class="kd">volatile</span> <span class="kt">int</span> <span class="n">writeOnly</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@GenerateMicroBenchmark</span>
<span class="nd">@Group</span><span class="o">(</span><span class="s">"falseSharing"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">reader</span><span class="o">(</span><span class="n">StateFalseSharing</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="na">readOnly</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@GenerateMicroBenchmark</span>
<span class="nd">@Group</span><span class="o">(</span><span class="s">"falseSharing"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">writer</span><span class="o">(</span><span class="n">StateFalseSharing</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="na">writeOnly</span><span class="o">++;</span>
<span class="o">}</span></code></pre>
<p>Regardons les résultats :</p>
<pre><code>Benchmark Mode Samples Mean Mean error Units
g.c.Benchmarks.falseSharing:reader avgt 18 5.038 0.617 ns/op
g.c.Benchmarks.falseSharing:writer avgt 18 78.530 3.598 ns/op
</code></pre>
<p>On vient presque de gagner un facteur 10.</p>
<p>Nous pouvons vérifier l’agencement mémoire de notre objet <code>StateBaseline</code> avec <a href="http://openjdk.java.net/projects/code-tools/jol/"><em>jol</em></a>, pour voir que nos deux variables ont bien été juxtaposées par le compilateur :</p>
<pre><code>gist.contended.Benchmarks.StateFalseSharing object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int StateFalseSharing.readOnly N/A
16 4 int StateFalseSharing.writeOnly N/A
20 4 (loss due to the next object alignment)
Instance size: 24 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
</code></pre>
<p>Sans rentrer dans les détails, statistiquement, il y a de fortes chances qu’elles se retrouvent dans la même ligne de cache.</p>
<h3 id="contended">@Contended</h3>
<p>La solution à notre problème est donc simplement d’espacer ces deux variables, quitte à perdre de l’espace. Ça paraît simple, mais, avant OpenJDK 8, cela demandait de très sérieusement connaître la machine virtuelle Java (ou lutter contre elle).</p>
<p>Fort du principe de localité, le comportement logique de la machine virtuelle Java est d’essayer d’entasser autant que possible les différents membres comme bon lui semble. La disposition (<em>layout</em>) d’un objet peut changer selon beaucoup de critères. Et l’utilisation d’un <a href="http://fr.wikipedia.org/wiki/Ramasse-miettes_%28informatique%29">ramasse‐miettes</a> n’aide pas, puisque ce dernier peut décider de déplacer un peu tout et n’importe quoi (notamment les tableaux utilisés pour les aligner). Bref, trouver une stratégie qui marche, est une source d’amusement inépuisable. Aleksey Shipilёv en a documenté quelques‐unes dans un <a href="http://hg.openjdk.java.net/code-tools/jmh/file/3b57fecd61bf/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_22_FalseSharing.java">banc d’essai JMH</a>, de même que <a href="http://mechanical-sympathy.blogspot.fr/2011/08/false-sharing-java-7.html">Martin Thompson</a>.</p>
<p>La JEP 142 propose d’ajouter une annotation <code>@Contended</code> pour identifier les variables, ou classes, qui doivent se retrouver seules sur une ligne de cache pour éviter le <em>false sharing</em>.</p>
<p>Essayons de l’utiliser :</p>
<pre><code class="java"> <span class="nd">@State</span><span class="o">(</span><span class="n">Scope</span><span class="o">.</span><span class="na">Group</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">StateContended</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">readOnly</span><span class="o">;</span>
<span class="nd">@Contended</span> <span class="kd">volatile</span> <span class="kt">int</span> <span class="n">writeOnly</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@GenerateMicroBenchmark</span>
<span class="nd">@Group</span><span class="o">(</span><span class="s">"contented"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">reader</span><span class="o">(</span><span class="n">StateContended</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="na">readOnly</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@GenerateMicroBenchmark</span>
<span class="nd">@Group</span><span class="o">(</span><span class="s">"contented"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">writer</span><span class="o">(</span><span class="n">StateContended</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="na">writeOnly</span><span class="o">++;</span>
<span class="o">}</span></code></pre>
<p>Vérifions avec <em>jol</em> puis avec JMH :</p>
<pre><code>gist.contended.Benchmarks.StateContended object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int StateContended.readOnly N/A
16 128 (alignment/padding gap) N/A
144 4 int StateContended.writeOnly N/A
148 4 (loss due to the next object alignment)
Instance size: 152 bytes (estimated, the sample instance is not available)
Space losses: 128 bytes internal + 4 bytes external = 132 bytes total
Benchmark Mode Samples Mean Mean error Units
g.c.Benchmarks.contented:reader avgt 18 0.742 0.006 ns/op
g.c.Benchmarks.contented:writer avgt 18 70.811 3.572 ns/op
</code></pre>
<p>On observe que la variable a bien été décalée, et l’on retrouve les performances initiales.</p>
<h3 id="limitations">Limitations</h3>
<p><code>@Contended</code> est une JEP d’OpenJDK, c’est‐à‐dire qu’il ne s’agit pas d’une spécification de Java ou de la machine virtuelle Java (JVM). L’annotation se trouve dans un paquet privé d’Oracle, et elle n’est disponible que pour les classes du kit de développement Java (JDK) par défaut (comme beaucoup de choses que le JDK se réserve précieusement). Si l’on veut l’utiliser, et donc se lier à OpenJDK, il faut passer l’option <code>-XX:-RestrictContended</code>.</p>
<p>Bien entendu, vu l’impact sur la consommation mémoire et la possibilité de réduire l’efficacité du cache, il faut bien savoir ce qu’on fait et l’utiliser avec parcimonie.</p>
<h3 id="comment-détecter-un-cas-de-false-sharing">Comment détecter un cas de false sharing</h3>
<p>Notre exemple était très simple et nous connaissions le problème. Malheureusement, dans la vraie vie, ce n’est pas aussi évident, et il n’existe pas à ma connaissance d’outil simple permettant de détecter le <em>false sharing</em>, quel que soit le langage. On peut suivre les conseils d’<a href="http://software.intel.com/en-us/articles/avoiding-and-identifying-false-sharing-among-threads">Intel</a> et les appliquer avec l’outil qu’ils fournissent ou avec <a href="http://blog.gmane.org/gmane.comp.linux.papi/month=20120201"><em>perf</em></a>, mais ça reste assez empirique.</p>
<p>Si l’on garde le principe du <em>false sharing</em> en tête, cela permet de surveiller les mauvaises pratiques dans les bouts d’infrastructure qui peuvent être affectés. En général, il faut que ça commence à aller sérieusement vite, donc avec des structures de données dédiées, pour que ça commence à devenir un problème.</p>
<h3 id="cas-courants">Cas courants</h3>
<p>Identiquement à notre exemple, un même objet possède deux membres qui sont utilisés par deux fils d’exécution différents. <s>Ça arrive, par exemple, quand un objet tient des statistiques.</s> Dans ce cas, on va annoter le membre avec <code>@Contended</code>.</p>
<p>On peut avoir aussi le cas de plusieurs instances d’une même classe qui préféreraient chacune être dans leur propre ligne de cache. Dans ce cas, on va annoter la classe. Cela fonctionne aussi si l’on met les instances dans un tableau ; cas courant, lorsque l’on fait travailler plusieurs fils d’exécution en parallèle.</p>
<p>Le dernier cas est le calcul de type matriciel avec plusieurs fils d’exécution. Dans ce cas, l’annotation ne peut rien et il faut concevoir son algorithme pour en tenir compte (tout comme on itère dans le bon sens). <a href="http://www.drdobbs.com/parallel/eliminate-false-sharing/217500206">Dr doobs</a> fournit un tel exemple.</p>
<p>J’ai essayé de fournir quelques exemples dans le <a href="https://gist.github.com/cykl/9924619#file-src_main_java_gist_contended_benchmarks-java">banc d’essai</a>.</p>
<h3 id="conclusion">Conclusion</h3>
<p><code>@Contended</code> ne devrait pas changer la vie de grand monde, hormis celle des gens qui pondent l’infrastructure de service à haute performance. Mais, elle ouvre la porte à une revendication de longue date : marier les bénéfices de la machine virtuelle Java avec les besoins des applications haute performance, en ouvrant l’accès au matériel et à des techniques contre l’esprit initial de Java, mais nécessaires.</p>
<p>Cette annotation ne répond absolument pas au besoin de pouvoir contrôler l’agencement d’un objet ou de choisir quels membres d’un objet doivent être regroupés. Elle ne résout pas non plus les problèmes d’indirection dus aux références pour les objets. Mais la pression monte doucement avec le nombre d’applications qui passent en <em>off‐the‐heap</em> ou en <em>mmap</em> lorsque nécessaire.</p>
<p>Enfin, le <em>false sharing</em> n’est pas le seul problème lié aux caches, il y a d’<a href="http://danluu.com/3c-conflict/">autres exemples</a>.<br>
Et, bien entendu, exploiter les caches correctement a un impact certain sur les performances d’une application.</p></div><div><a href="https://linuxfr.org/news/openjdk-8-jep-142-false-sharing.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/101757/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/openjdk-8-jep-142-false-sharing#comments">ouvrir dans le navigateur</a>
</p>
ckylDavy DefaudZeroHeureFlorent Zarapalm123tuiu polBenoît Sibaudhttps://linuxfr.org/nodes/101757/comments.atomtag:linuxfr.org,2005:News/352032014-03-28T14:19:56+01:002014-03-28T15:23:57+01:00Java 8 et NetBeans 8 sont disponiblesLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Oracle a <a href="http://mail.openjdk.java.net/pipermail/announce/2014-March/000166.html">annoncé</a> la mise à disposition de la nouvelle version standard de Java, huitième du nom. Deux ans et sept mois après Java 7, la publication de cette nouvelle version a été retardée afin d’améliorer la sécurité.</p>
<p>Et pour permettre d’exploiter au mieux ce nouveau JDK, une nouvelle version de l’environnement de développement <a href="http://fr.wikipedia.org/wiki/NetBeans" title="Définition Wikipédia">NetBeans</a> est également disponible et porte le même numéro. Côté <a href="https://fr.wikipedia.org/wiki/Eclipse_%28projet%29">Eclipse</a>, un <a href="https://wiki.eclipse.org/JDT/Eclipse_Java_8_Support_For_Kepler">correctif</a> est proposé et concernant IntelliJ, Java 8 est pris en charge dans la version 13.1 sortie la semaine dernière.</p>
<p>Ces deux sorties marquent la volonté d’Oracle de convaincre les développeurs.</p></div><ul><li>lien nᵒ 1 : <a title="http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html" hreflang="en" href="https://linuxfr.org/redirect/89836">Notes de version : What’s New in JDK 8</a></li><li>lien nᵒ 2 : <a title="https://netbeans.org/community/releases/80/" hreflang="en" href="https://linuxfr.org/redirect/89846">NetBeans 8</a></li><li>lien nᵒ 3 : <a title="http://www.oracle.com/technetwork/java/javase/downloads/index.html" hreflang="en" href="https://linuxfr.org/redirect/89847">Téléchargement</a></li><li>lien nᵒ 4 : <a title="http://openjdk.java.net/projects/jdk8/features" hreflang="en" href="https://linuxfr.org/redirect/89848">JDK 8 features</a></li><li>lien nᵒ 5 : <a title="http://linuxfr.org/news/naissance-dun-g%C3%A9ant-java" hreflang="fr" href="https://linuxfr.org/redirect/89898">[LinuxFr.org] Naissance d’un géant : Java</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#nouveaut%C3%A9s-java8">Nouveautés Java 8</a><ul>
<li>
<a href="#les-lambdas">Les lambdas</a><ul>
<li><a href="#interfaces-fonctionnelles-functionalinterface">Interfaces fonctionnelles (FunctionalInterface)</a></li>
</ul>
</li>
<li><a href="#api-stream">API Stream</a></li>
<li><a href="#nashorn-javascript-dans-java">Nashorn, JavaScript dans Java</a></li>
<li><a href="#impl%C3%A9mentation-pard%C3%A9faut-dans-les-interfaces-defendermethods">Implémentation par défaut dans les interfaces (<em>Defender Methods</em>)</a></li>
<li><a href="#m%C3%A9thodes-statiques-dans-les-interfaces">Méthodes statiques dans les interfaces</a></li>
<li><a href="#api-date">API Date</a></li>
<li><a href="#disparition-du-permgen">Disparition du Permgen</a></li>
</ul>
</li>
</ul><h2 id="nouveautés-java8">Nouveautés Java 8</h2>
<h3 id="les-lambdas">Les lambdas</h3>
<p>C’est une technique pour écrire des fonctions qui ne sont pas nommées et directement définies là où elles sont appelées. Cela permet une écriture plus simple pour les fonctions qui ne sont appelées qu’à un seul endroit du code. L’exemple classique est pour définir une fonction de tri :</p>
<pre><code class="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Users</span> <span class="o">{</span>
<span class="kd">public</span> <span class="n">String</span> <span class="n">username</span><span class="o">;</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="n">karma</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Sort users by karma</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">sortUser</span><span class="o">(</span><span class="n">Users</span><span class="o">[]</span> <span class="n">users</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Arrays</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">users</span><span class="o">,</span> <span class="o">(</span><span class="n">Users</span> <span class="n">u1</span><span class="o">,</span> <span class="n">Users</span> <span class="n">u2</span><span class="o">)</span> <span class="o">-></span> <span class="o">{</span> <span class="k">return</span> <span class="n">u1</span><span class="o">.</span><span class="na">karma</span> <span class="o">-</span> <span class="n">u2</span><span class="o">.</span><span class="na">karma</span><span class="o">;</span> <span class="o">});</span>
<span class="o">}</span>
<span class="o">}</span></code></pre>
<p>Avant l’introduction des lambdas, dans cet exemple, il fallait définir une implémentation pour <code>Comparator</code>, ce qui était un peu plus verbeux :</p>
<pre><code class="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Users</span>
<span class="o">{</span>
<span class="kd">public</span> <span class="n">String</span> <span class="n">username</span><span class="o">;</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="n">karma</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Sort users by karma</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">sortUser</span><span class="o">(</span><span class="n">Users</span><span class="o">[]</span> <span class="n">users</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Arrays</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">users</span><span class="o">,</span> <span class="k">new</span> <span class="n">Comparator</span><span class="o"><</span><span class="n">Users</span><span class="o">>()</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">compare</span><span class="o">(</span><span class="n">Users</span> <span class="n">u1</span><span class="o">,</span> <span class="n">Users</span> <span class="n">u2</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">u1</span><span class="o">.</span><span class="na">karma</span> <span class="o">-</span> <span class="n">u2</span><span class="o">.</span><span class="na">karma</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">});</span>
<span class="o">}</span>
<span class="o">}</span></code></pre>
<h4 id="interfaces-fonctionnelles-functionalinterface">Interfaces fonctionnelles (FunctionalInterface)</h4>
<p>Pour implémenter les lambdas, le langage s’appuie sur les interfaces fonctionnelles, c’est‐à‐dire des interfaces possédant une seule méthode abstraite. Toutes les interfaces respectant cette condition sont, de fait, des interfaces fonctionnelles. Toutefois, il est possible d’utiliser l’annotation <code>@FunctionalInterface</code> pour qu’une erreur soit levée si une interface ne respecte plus cette condition.</p>
<h3 id="api-stream">API Stream</h3>
<p>L’<a href="http://fr.wikipedia.org/wiki/Interface_de_programmation">interface de programmation</a> (API) <em>Stream</em> a été ajoutée, permettant de représenter des données sous forme de flux et de les manipuler de manière efficace. Cette API s’appuie largement sur les fonctions lambdas décrites plus haut.</p>
<p>Les habitués des tubes (<em>pipes</em>) du Shell (il y en a par ici ? :)), des langages fonctionnels et de certains autres comme Perl ne devraient pas être trop dépaysés par cette manière de programmer.</p>
<p>Voici un exemple sorti de la <a href="http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html">documentation officielle</a> :</p>
<pre><code class="java"><span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">widgets</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
<span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">b</span> <span class="o">-></span> <span class="n">b</span><span class="o">.</span><span class="na">getColor</span><span class="o">()</span> <span class="o">==</span> <span class="n">RED</span><span class="o">)</span>
<span class="o">.</span><span class="na">mapToInt</span><span class="o">(</span><span class="n">b</span> <span class="o">-></span> <span class="n">b</span><span class="o">.</span><span class="na">getWeight</span><span class="o">())</span>
<span class="o">.</span><span class="na">sum</span><span class="o">();</span></code></pre>
<p>Ici, <code>widgets</code> est une <code>Collection<Widget></code>, mais cette API peut être utilisée avec toute sorte de flux de données, comme des fichiers ou des <a href="http://fr.wikipedia.org/wiki/Berkeley_sockets"><em>sockets</em></a>. Il est aussi possible de créer ses propres types de flux <em>stream</em>.</p>
<p>Enfin, il est possible de paralléliser les traitements sur ces flux de manière simple (plus simple que gérer des <code>Threads</code>).</p>
<h3 id="nashorn-javascript-dans-java">Nashorn, JavaScript dans Java</h3>
<p>Java inclut désormais un nouveau moteur JavaScript qui remplace le vieillissant Rhino. Il permet donc d’invoquer du code JavaScript directement dans le code Java. Il est évidemment possible d’interagir avec le code Java en appelant du code Java en JavaScript, ou même en étendant des classes Java.</p>
<p>Il est aussi possible de l’utiliser directement en ligne de commande comme un script classique et d’éviter d’écrire un <em>wrapper</em> Java. La commande s’appelle <code>jjs</code>.</p>
<h3 id="implémentation-pardéfaut-dans-les-interfaces-defendermethods">Implémentation par défaut dans les interfaces (<em>Defender Methods</em>)</h3>
<p>Jusqu’à la version précédente, les interfaces Java ne pouvaient contenir de code, uniquement des déclarations de méthodes. À partir de cette version, les implémentations de méthodes statiques et les implémentations par défaut de méthodes sont possibles. Ces dernières sont des implémentations des méthodes qui seront utilisées si la méthode n’est pas redéfinie dans une autre implémentation qui étend celle‐ci ou une classe qui implémente l’interface sans implémentation pour la méthode.</p>
<p>Cela fait resurgir le <a href="http://fr.wikipedia.org/wiki/Probl%C3%A8me_du_diamant">problème de l’héritage en diamant</a> qui était évité par l’absence d’héritage multiple de classe et que les interfaces permettaient d’éviter par rapport aux classes abstraites. Que faire lorsqu’une méthode est définie dans plusieurs interfaces implémentées dans une classe ? Prenons l’exemple suivant :</p>
<pre><code class="java"><span class="kd">interface</span> <span class="nc">A</span> <span class="o">{</span>
<span class="kt">void</span> <span class="nf">m</span><span class="o">()</span> <span class="k">default</span> <span class="o">{}</span>
<span class="o">}</span>
<span class="kd">interface</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="n">A</span> <span class="o">{}</span>
<span class="kd">interface</span> <span class="nc">C</span> <span class="kd">extends</span> <span class="n">A</span> <span class="o">{}</span>
<span class="kd">class</span> <span class="nc">D</span> <span class="kd">implements</span> <span class="n">B</span><span class="o">,</span> <span class="n">C</span> <span class="o">{}</span></code></pre>
<p>Ce cas est assez simple, <em>D</em> héritera de l’implémentation dans <em>A</em>. Si <em>B</em> ou <em>C</em> implémentent la méthode, ce sera cette implémentation qui sera utilisée (l’implémentation la plus spécifique est utilisée). Si <em>B</em> et <em>C</em> implémentent la méthode, il faudrait spécifier explicitement quelle méthode sera utilisée.</p>
<h3 id="méthodes-statiques-dans-les-interfaces">Méthodes statiques dans les interfaces</h3>
<p>En plus des méthodes par défaut, il est possible de définir des méthodes statiques dans les interfaces. Il n’y a pas de différence avec les méthodes statiques dans une classe.</p>
<h3 id="api-date">API Date</h3>
<p>Beaucoup de monde attendait une évolution (une révolution ?) de l’<a href="http://fr.wikipedia.org/wiki/Interface_de_programmation">interface de programmation</a> (API) <em>Date</em> et utilisait <em>JodaTime</em> à la place de l’API standard.</p>
<p>Java 8 apporte une nouvelle API pour gérer les dates, qui est divisée en deux parties :</p>
<ul>
<li>le temps humain, principalement porté par <code>LocalDate</code> et <code>LocalTime</code> gère une date prenant en compte le fuseau horaire et possédant distinctement différents champs (pour l’heure, le jour, etc.) ;</li>
<li>le temps machine, qui est un horodatage (<em>timestamp</em>) et qui s’appuie sur les classes <code>Instant</code> et <code>Duration</code>.</li>
</ul><p>Grande nouvelle : cette nouvelle API est <em>thread-safe</em> ! Je vous laisse découvrir plus en détail cette API au travers du tutoriel de Yohan Beschi, <a href="http://soat.developpez.com/tutoriels/java/time-date-java8/"><em>Tutoriel sur les nouveautés du langage 8 : la nouvelle API Date et Time</em></a>.</p>
<h3 id="disparition-du-permgen">Disparition du Permgen</h3>
<p>C’est une évolution spécifique à l’implémentation de référence, mais ça fera plaisir à beaucoup de monde en évitant des erreurs du type <code>java.lang.OutOfMemoryError: PermGen space</code>. Le <em>permgen</em> stockait les définitions de classes définies dans le programme en cours, et sa taille pouvait poser un problème pour les grosses applications utilisant beaucoup de classes ou les générant en cours de fonctionnement. C’est donc un point en moins à surveiller pour les mises en production.</p></div><div><a href="https://linuxfr.org/news/java-8-et-netbeans-8-sont-disponibles.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/101641/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/java-8-et-netbeans-8-sont-disponibles#comments">ouvrir dans le navigateur</a>
</p>
Xavier ClaudeDavy DefaudbarmicjBAudZeroHeurepalm123NÿcodomakSébastien Koechlinhttps://linuxfr.org/nodes/101641/comments.atomtag:linuxfr.org,2005:News/349272013-12-24T00:30:13+01:002013-12-24T16:29:14+01:00JQM, un serveur de batchs asynchrones en JavaLicence CC By‑SA http://creativecommons.org/licenses/by-sa/3.0/deed.fr<div><p>JQM (Job Queue Management) est un gestionnaire de batch sous <a href="http://www.apache.org/licenses/LICENSE-2.0">licence Apache</a> qui permet de traiter sur des noeuds de traitement répartis toutes les tâches potentiellement longues qui ne sont pas désirables dans un serveur d'application à travers un système de files d'attente. Ce logiciel s'adresse à toute application qui souhaite gérer l'exécution de ses tâches hors du serveur d'application.</p>
<p>Une tâche peut être déclenchée depuis un appel Web Service ou une API par une application web, un ordonnanceur ou un flux d'interface. </p>
<p>L'outil propose de nombreuses fonctionnalités comme l’arrêt d’une tâche, la récupération de fichiers générés, la priorisation d’une tâche et bien d’autres. JQM a été développé en Java SE 1.6, utilise <a href="http://hibernate.org/">Hibernate</a>/JPA 2.0 comme <a href="http://fr.wikipedia.org/wiki/Mapping_objet-relationnel">ORM</a>, et une base de donnée comme référentiel de configuration et file d'attente des traitements. JQM est compatible avec les bases <a href="http://hsqldb.org/">HSQL</a>, MySQL et Oracle, les serveurs d’application WebSphere et <a href="https://glassfish.java.net/fr/">Glassfish</a> (prochainement Tomcat) pour l'API cliente et gère les ressources <a href="http://fr.wikipedia.org/wiki/Java_Naming_and_Directory_Interface">JNDI</a> pour les bases de données et les brokers de messages. </p>
<p>L'outil est compatible avec les projets <a href="http://maven.apache.org/">Maven</a> et tout particulièrement la gestion des dépendances et des projets parents.</p></div><ul><li>lien nᵒ 1 : <a title="https://github.com/enioka/jqm" hreflang="fr" href="https://linuxfr.org/redirect/88863">Code source sur GitHub</a></li></ul><div><h3 id="architecture">Architecture</h3>
<p>JQM est composé de trois grandes parties :</p>
<ul>
<li>les moteurs de traitements (des JVM standalone) qui exécutent les tâches. Il est possible de déployer plusieurs moteurs (ou noeuds) de traitements pour des raisons de performance ou de haute disponibilité</li>
<li>une base de données qui joue le rôle de file de traitement et de référentiel de configuration</li>
<li>les clients (une application Web dans un serveur d'application, une ligne de commande, un ordonnanceur, une autre tâche (<em>job</em>) JQM etc.) qui soumettent des tâches à JQM</li>
</ul><p>Les noeuds de traitement sont reliés à des files de traitement en base de données et ont chacun un intervalle de polling et un nombre défini de tâches pouvant tourner simultanément.</p>
<p>Par exemple:</p>
<ul>
<li>VIPqueue = 10 tâches en simultané + intervalle de polling de 1 seconde</li>
<li>SLOWqueue = 3 tâches en simultané + intervalle de polling de 15 min</li>
</ul><p><img src="//img.linuxfr.org/img/687474703a2f2f626c6f672e656e696f6b612e636f6d2f7075626c69632f696d675f626c6f672f4a514d2f2e736368656d615f6a716d5f6d2e6a7067/.schema_jqm_m.jpg" alt="schema_JQM" title="Source : http://blog.enioka.com/public/img_blog/JQM/.schema_jqm_m.jpg"></p>
<h3 id="cycle-de-vie-dune-tâche">Cycle de vie d'une tâche</h3>
<p>Le cycle de vie d'une tâche passe par quatre états différents.</p>
<p>Après avoir été ajoutée à la file d'attente, la tâche prend le status <em>SUBMITTED</em>. Une fois que la tâche est "attrapée" par un noeud, son statut passe à l'état <em>ATTRIBUTED</em> suivi de <em>RUNNING</em> une fois que l'exécution de celle-ci a commencé.</p>
<p>La tâche à la fin de son exécution a deux états possibles, <em>CRASHED</em> si la tâche n'a pas fonctionné correctement ou <em>ENDED</em> si tout le processus s'est déroulé correctement.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f626c6f672e656e696f6b612e636f6d2f7075626c69632f696d675f626c6f672f4a514d2f2e6379636c655f6f665f6c6966655f4a514d5f6d2e6a7067/.cycle_of_life_JQM_m.jpg" alt="Cycle_de_vie_d'une_tache" title="Source : http://blog.enioka.com/public/img_blog/JQM/.cycle_of_life_JQM_m.jpg"></p>
<h3 id="fonctionnalités">Fonctionnalités</h3>
<h4 id="pour-les-développeurs">Pour les développeurs</h4>
<ul>
<li><p>Pour les développeurs de traitement :<br>
une tâche est définie comme telle une fois qu'elle étend (<em>extends</em>) la classe JobBase de l'API jqm-api.<br>
Au sein d'une tâche, il est possible de récupérer des ressources via JNDI (base de données, broker de message, répertoire de traitement…), d'envoyer une progression, un message de log ou de mettre en file une autre tâche.</p></li>
<li>
<p>Pour les clients des traitements :<br>
Il existe plusieurs moyens d'utiliser<br>
JQM. </p>
<ul>
<li>Par le biais de l'API jqm-clientapi qui permet d'avoir toutes les fonctionnalités existantes, à savoir la possibilité de mettre une tâche en file, de regarder son état, de l'annuler, de le changer de file et bien d'autres ;</li>
<li>Par le biais d'un web service ;</li>
<li>Par une interface en ligne de commande ;</li>
<li>Par une IHM web (très frustre à l'heure actuelle).</li>
</ul>
</li>
</ul><h4 id="pour-les-administrateurs">Pour les administrateurs</h4>
<p>Un administrateur a la possibilité de consulter les logs, de gérer les connexions JNDI, de paramétrer les associations entre les tâches et les files.</p>
<h3 id="exemple-de-tâche">Exemple de tâche</h3>
<pre><code class="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Caller</span> <span class="kd">extends</span> <span class="n">JobBase</span>
<span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">()</span>
<span class="o">{</span>
<span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">></span> <span class="n">params</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">>();</span>
<span class="n">p</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"myParam1"</span><span class="o">,</span> <span class="s">"Pouet"</span><span class="o">);</span>
<span class="n">p</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"myParam2"</span><span class="o">,</span> <span class="s">"tut tut"</span><span class="o">);</span>
<span class="c1">// enQueue is a JobBase method.</span>
<span class="c1">// It is used to enqueue a Job, here “Called”.</span>
<span class="n">enQueue</span><span class="o">(</span><span class="s">"CalledJob"</span><span class="o">,</span> <span class="s">"Bob"</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span>
<span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="n">params</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre>
<h3 id="exemple-dintégration-de-jqm-dans-un-si">Exemple d'intégration de JQM dans un SI</h3>
<p>Dans cet exemple, JQM est utilisé pour gérer une intégration au fil de l'eau de message dans un ERP qui ne possède qu'une interface d'entrée de type table / prodédure stockée.</p>
<p>JQM joue un rôle de « joint de dilatation » entre un système événementiel qui gère des pics à 200 000 messages par heure et une interface de type procédure stockée qui traite des données en masse mais ne se prête pas à de nombreuses exécutions simultanées.</p>
<p>Chaque message est traité par un thread d'un conteneur MDB (Message Driven Bean) et déclenche une tâche JQM. La file de tâches JQM est paramétrée pour n'exécuter qu'une seule tâche à la fois et annuler les lancements surnuméraires. La tâche lance la procédure stockée de l'ERP qui traite toutes les données en attente dans la table d'interface.</p>
<p>En pic, plusieurs centaines de messages n'occasionneront qu'un ou deux lancement de la procédure stockée qui traitera en masse les données. Le système permet ainsi de rester très réactif en période creuse (au contraire des systèmes de type batch cyclique) tout en permettant la montée en charge lors des pics.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f626c6f672e656e696f6b612e636f6d2f7075626c69632f696d675f626c6f672f4a514d2f2e696e746567726174696f6e5f6a716d5f6d2e6a7067/.integration_jqm_m.jpg" alt="integration_JQM" title="Source : http://blog.enioka.com/public/img_blog/JQM/.integration_jqm_m.jpg"></p>
<h3 id="origine-du-projet">Origine du projet</h3>
<p>Le projet a été développé par la <a href="http://www.enioka.com">société Enioka</a> dans le cadre d'un projet pour l'un de ses clients pour l'intégration d'un ERP.</p>
<p>Suite à la réalisation de ce projet, il a été convenu que JQM deviendrait open source afin de combler le manque actuel de ce type d'outils libres dans un contexte java SE/EE 6.</p>
<p>Le code source et la documentation sont <a href="https://github.com/enioka/jqm">disponibles sur Github</a>.</p></div><div><a href="https://linuxfr.org/news/jqm-un-serveur-de-batchs-asynchrones-en-java.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/100752/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/jqm-un-serveur-de-batchs-asynchrones-en-java#comments">ouvrir dans le navigateur</a>
</p>
pierre.coppeeBenoît SibaudSebastienpalm123claudexhttps://linuxfr.org/nodes/100752/comments.atomtag:linuxfr.org,2005:News/344002013-07-04T23:07:54+02:002013-07-04T23:07:53+02:00Ametys, le CMS java open source français qui monteLicence CC By‑SA http://creativecommons.org/licenses/by-sa/3.0/deed.fr<div><p>La nouvelle <a href="http://www.ametys.org/fr/actualites/les-nouveautes-produits/version-3-5-du-cms-ametys.html#version-3-5-du-cms-ametys-actualite">version 3.5</a> du CMS libre Ametys vient d'être livrée. Toujours téléchargeable gratuitement sur le site <a href="http://www.ametys.org">ametys.org</a>, cette nouvelle version ajoute des améliorations notables sur la gestion multi-site et s'enrichit de nouveaux plugins et services tout en améliorant le rendu back office et l'expérience utilisateur.</p>
<p>Visitez le site démo d'Ametys et connectez-vous au backoffice : <a href="http://demo.ametys.org">demo.ametys.org</a></p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f616d657479732e636d732e66722f6d656469612f616d657479735f6261636b5f6f66666963655f726573706f6e736976655f5f3037303832333030305f313135325f30343036323031332e706e67/ametys_back_office_responsive__070823000_1152_04062013.png" alt="Ametys CMS" title="Source : http://ametys.cms.fr/media/ametys_back_office_responsive__070823000_1152_04062013.png"></p>
<p>Tous les détais sur Ametys dans la seconde partie de la dépêche !</p></div><ul><li>lien nᵒ 1 : <a title="http://www.ametys.org" hreflang="fr" href="https://linuxfr.org/redirect/86990">Ametys CMS</a></li><li>lien nᵒ 2 : <a title="http://demo.ametys.org" hreflang="fr" href="https://linuxfr.org/redirect/86991">Site de démo</a></li><li>lien nᵒ 3 : <a title="http://www.ametys.org/fr/telecharger/cms-ametys.html" hreflang="fr" href="https://linuxfr.org/redirect/86992">Téléchargement gratuit</a></li><li>lien nᵒ 4 : <a title="http://www.ametys.org/forum/" hreflang="fr" href="https://linuxfr.org/redirect/86993">Forum Ametys</a></li><li>lien nᵒ 5 : <a title="https://sourceforge.net/projects/ametys/files/latest/download?source=directory" hreflang="fr" href="https://linuxfr.org/redirect/86994">Téléchargement via Sourceforge</a></li></ul><div><p>Créé dans les années 2000 et particulièrement adapté dans un contexte de partage et de publication de contenus fédéré entre plusieurs sites, Ametys se différencie avant tout par son interface de contribution ergonomique et conviviale très proche des outils de bureautiques (Microsoft Word). </p>
<p>Un rapide aperçu des fonctionnalités clés du CMS :</p>
<ul>
<li>ergonomie & simplicité (Glisser-déposer, éditeur Wysiwyg, …) ;</li>
<li>plate-forme multi-sites ;</li>
<li>facilite le partage de contenus ;</li>
<li>fonctionnalités Web 2.0 : Moteur de blogs, Connexion réseaux sociaux, Widgets personnalisables ;</li>
<li>dernières normes d’accessibilité ;</li>
<li>gestion de workflow facilement personnalisables ;</li>
<li>atelier charte graphique ;</li>
<li>plugin cartographie ;</li>
<li>plugin enquêtes en ligne avec statistiques.</li>
</ul><p>Smile, 1er intégrateur européen de solutions open source, livre son expertise sur la solution : <em>"Ametys répond parfaitement aux besoins des entreprises et administrations publiques à la recherche d’une solution de gestion de contenus modulable et fiable."</em></p></div><div><a href="https://linuxfr.org/news/ametys-le-cms-java-open-source-francais-qui-monte.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/98976/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/ametys-le-cms-java-open-source-francais-qui-monte#comments">ouvrir dans le navigateur</a>
</p>
Nÿcopalm123Nils Ratusznikhttps://linuxfr.org/nodes/98976/comments.atomtag:linuxfr.org,2005:News/343792013-07-01T21:45:45+02:002013-07-01T21:45:45+02:00CapeDwarf, Google App Engine pour JBossLicence CC By‑SA http://creativecommons.org/licenses/by-sa/3.0/deed.fr<div><p>Google App Engine est un service de <em>Platform as a Service (PaaS)</em>. C'est-à-dire qu'au lieu de fournir une infrastructure pour y installer ce qu'on veut, Google fournit des API pour y déployer les applications que l'on souhaite. CapeDwarf est la réimplémentation par Red Hat de ces API pour JBoss, un serveur d'application Java EE libre (un serveur d'application, c'est aussi un ensemble d'API pour déployer facilement des applications).</p>
<p>Red Hat et Google travaillent ensemble sur un système de test open source permettant de valider des implémentations alternatives de Google App Engine (telles que CapeDwarf). L'intérêt est d'avoir des API plus orientées cloud que JEE sur des infrastructures privées ou de pouvoir migrer de l'une à l'autre plus facilement.</p></div><ul><li>lien nᵒ 1 : <a title="http://www.jboss.org/capedwarf" hreflang="en" href="https://linuxfr.org/redirect/86918">CapeDwarf</a></li><li>lien nᵒ 2 : <a title="http://googlecloudplatform.blogspot.be/2013/06/google-app-engine-running-in-private-cloud-with-capedrawf.html" hreflang="en" href="https://linuxfr.org/redirect/86919">L'annonce sur le blog de Google Cloud Platform</a></li></ul><div></div><div><a href="https://linuxfr.org/news/capedwarf-google-app-engine-pour-jboss.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/98905/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/capedwarf-google-app-engine-pour-jboss#comments">ouvrir dans le navigateur</a>
</p>
Xavier ClaudeZeroHeureXavier Teyssierhttps://linuxfr.org/nodes/98905/comments.atomtag:linuxfr.org,2005:News/343752013-06-30T09:54:37+02:002013-06-30T09:55:25+02:00L’environnement de développement Eclipse 4.3 est disponibleLicence CC By‑SA http://creativecommons.org/licenses/by-sa/3.0/deed.fr<div><p>La <a href="http://fr.wikipedia.org/wiki/Fondation%20Eclipse" title="Définition Wikipédia">Fondation Eclipse</a> vient d’annoncer la disponibilité d’une nouvelle version de l’environnement de développement libre <a href="http://fr.wikipedia.org/wiki/Eclipse_%28projet%29">Eclipse</a> numéroté 4.3, nom de code <a href="http://fr.wikipedia.org/wiki/Johannes_Kepler">Kepler</a>, pour Linux, Mac OS X et Windows.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e65636c697073652e6f72672f65636c697073652e6f72672d636f6d6d6f6e2f7468656d65732f4e6f76612f696d616765732f65636c697073652e706e67/eclipse.png" alt="Eclipse" title="Source : http://www.eclipse.org/eclipse.org-common/themes/Nova/images/eclipse.png"></p>
<p>Eclipse Kepler se compose de 71 projets, ce qui représente 58 millions de lignes de code. Cette nouvelle version prend en charge <a href="http://fr.wikipedia.org/wiki/Java%20EE" title="Définition Wikipédia">Java EE</a> 7 (sorti le 12 juin dernier) et apporte de nouvelles améliorations concernant l’interface et les performances.</p>
<p>Kepler apporte de nouvelles améliorations concernant l’interface et les performances. Les nouvelles fonctionnalités sont nombreuses, bien détaillées et illustrées de captures d’écran - cliquez sur les liens ci dessous. Voir la liste en français en seconde partie.</p></div><ul><li>lien nᵒ 1 : <a title="http://www.eclipse.org" hreflang="en" href="https://linuxfr.org/redirect/86897">Eclipse.org</a></li><li>lien nᵒ 2 : <a title="http://www.eclipse.org/org/press-release/20130626_kepler_francais.php" hreflang="fr" href="https://linuxfr.org/redirect/86898">Annonce de la disponibilité d'Eclipse 4.3</a></li><li>lien nᵒ 3 : <a title="http://download.eclipse.org/eclipse/downloads/drops4/R-4.3-201306052000/news/eclipse-news-part1.html" hreflang="en" href="https://linuxfr.org/redirect/86899">Nouvelles fonctionnalités de l'interface</a></li><li>lien nᵒ 4 : <a title="http://download.eclipse.org/eclipse/downloads/drops4/R-4.3-201306052000/news/eclipse-news-part2.html" hreflang="en" href="https://linuxfr.org/redirect/86900">Nouvelles fonctionnalités pour les développeurs Java</a></li><li>lien nᵒ 5 : <a title="http://download.eclipse.org/eclipse/downloads/drops4/R-4.3-201306052000/news/eclipse-news-part3.html" hreflang="en" href="https://linuxfr.org/redirect/86901">Nouvelles API</a></li><li>lien nᵒ 6 : <a title="http://download.eclipse.org/eclipse/downloads/drops4/R-4.3-201306052000/news/eclipse-news-part4.html" hreflang="en" href="https://linuxfr.org/redirect/86902">Nouvelles fonctionnalités pour les développeurs de plug-in</a></li><li>lien nᵒ 7 : <a title="http://www.eclipse.org/downloads/?osType=linux" hreflang="en" href="https://linuxfr.org/redirect/86903">Téléchargement</a></li></ul><div><h2 id="daprs-lannonce-de-presse">D'après l'annonce de presse</h2>
<p>Comme chaque année, la communauté Eclipse coordonne une sortie majeure de ses projets Open Source fin juin. <br>
Cette sortie simultanée est une bonne illustration de l'efficacité des processus de développement en logiciel libre : appliqués ici au développement distribué à grande échelle (Eclipse Kepler réunit 71 projets, 420 développeurs et plus de 58 millions de lignes de code), elle permet aux utilisateurs de mettre à jour, en une fois, les nouvelles versions de leurs projets, en s'appuyant sur un agenda prévisible de sortie.</p>
<p>Eclipse est une plateforme de développement ouverte composée de frameworks extensibles, outils et runtimes pour construire, déployer, et gérer le cycle de vie logiciel. </p>
<h3 id="voici-quelques-unes-des-principales-nouveauts-pour-kepler-">Voici quelques-unes des principales nouveautés pour Kepler :</h3>
<h4 id="support-de-java-ee7">Support de Java EE7</h4>
<p>– La version 3.5 du projet Eclipse Web Tools (WTP) apporte le support de Java EE 7, lui-même récemment publié, incluant le support pour JPA 2.1, JSF 2.2, JAX-RS 2.0, Servlet 3.1, EJB 3.2, Connector 1.7, App Client 7.0 et EAR 7.0. <br>
Les assistants de création, les aides au contenu et de validation ont été mis à jour. </p>
<h4 id="nouvelle-suite-pour-la-gestion-des-processus-mtier">Nouvelle suite pour la gestion des processus métier</h4>
<p>– Eclipse Stardust 1.0 apporte un moteur et des outils de gestion de processus métier. Eclipse Stardust inclut un environnement de modélisation qui permet de créer et de débugger les modèles de workflow, un moteur de processus pour exécuter des applications BPM, un portail web pour les exécutions basées sur un navigateur et la surveillance des processus métier et un composant de reporting basé sur BIRT pour la surveillance d’exécution et le reporting des applications BPM.</p>
<h4 id="extensibilit-et-utilisation-dun-ide-bas-sur-le-web">Extensibilité et utilisation d’un IDE basé sur le web</h4>
<p>– Orion 3.0 apporte des améliorations sur l’utilisation et l’extension de l’IDE web Orion. Il peut maintenant être facilement installé comme un fichier WAR dans un serveur d’applications Java, permettant de déployer vers des services cloud plus facilement. L’utilisation d’Orion a également été améliorée pour inclure la navigation de fichiers directement dans l’éditeur, de nouveaux raccourcis (vi et Emacs), sauvegarde automatique / chargement automatique et un nouveau style visuel.</p>
<h4 id="nouveau-support-pour-le-big-data">Nouveau support pour le Big Data</h4>
<p>– Eclipse BIRT 4.3 introduit le support des bases de données MongoDB et Cassandra et permet une intégration simplifiée pour les capacités de visualisation BIRT dans des applications Big Data. C’est un ajout au support existant d’Hadoop fourni par BIRT.</p>
<h4 id="meilleure-intgration-pour-la-revue-de-code">Meilleure intégration pour la revue de code</h4>
<p>– Grâce à Mylyn 3.9, il est désormais beaucoup plus facile de réaliser des revues de code dans Eclipse. La nouvelle vue navigateur intégrée avec Gerrit démontre la vue structurée de tous les fichiers et commentaires d’une revue.</p>
<h4 id="amlioration-de-lintgration-avec-maven-pour-les-dveloppeurs-javaee">Amélioration de l’intégration avec Maven pour les développeurs JavaEE</h4>
<p>– Nouveau support pour l’intégration Maven avec le projet Eclipse Web Tools (WTP) fournissant un ensemble de connecteurs qui ajoute le support Maven pour les projets Eclipse Java EE, incluant les projets war, ejb, et rar.</p>
<h2 id="nouveauts-de-linterface">Nouveautés de l'interface</h2>
<h3 id="changements-ergonomiques">Changements ergonomiques</h3>
<ul>
<li>Les fenêtres peuvent être détachées sur plusieurs moniteurs tout en restant à jour ;</li>
<li>Assistant de migration pour les installations partagées d'Eclipse ;</li>
<li>Correction d'installation ;</li>
<li>Les barres d'outils peuvent être repositionnées ;</li>
<li>Raccourcis dans le dialogue d'ouverture de ressources ;</li>
<li>Les recherches peuvent se faire sur des mots entiers ;</li>
<li>La fenêtre de dialogue s'ouvre avec le dernier mot recherché ; </li>
<li>Une option de lancement permet maintenant d'arrêter un plugin bogué sans arrêter Eclipse.</li>
</ul><h3 id="dveloppement">Développement</h3>
<ul>
<li>
<a href="http://www.eclipse.org/swt/">SWT</a> pour GTK3</li>
<li>Améliorations de performances.</li>
</ul><h3 id="outils">Outils</h3>
<ul>
<li>Importation projets imbriqués ;</li>
<li>Les warnings peuvent être affichés au lancement d'une fenêtre de configuration ;</li>
<li>Une option permet de ne pas utliser <code>-XstartOnFirstThread</code> ;</li>
<li>Prise en charge de <em>augment task</em> pour Ant.</li>
</ul></div><div><a href="https://linuxfr.org/news/l-environnement-de-developpement-eclipse-4-3-est-disponible.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/98880/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/l-environnement-de-developpement-eclipse-4-3-est-disponible#comments">ouvrir dans le navigateur</a>
</p>
jZeroHeureclaudexbubar🦥palm123Nÿcohttps://linuxfr.org/nodes/98880/comments.atomtag:linuxfr.org,2005:News/341472013-05-01T10:50:39+02:002013-05-01T15:41:15+02:00Qi4j SDK 2.0 - Framework de Programmation Orientée CompositeLicence CC By‑SA http://creativecommons.org/licenses/by-sa/3.0/deed.fr<div><p>Après deux ans de dur labeur, la Communauté Qi4j lance aujourd'hui la deuxième génération de son framework de Programmation Orientée Composite, disponible sous la très libérale licence Apache 2.0.</p>
<p>
<img src="//img.linuxfr.org/img/687474703a2f2f7169346a2e6f72672f67726170686963732f5169346a2d4c6f676f2d36347836342e706e67/Qi4j-Logo-64x64.png" alt="Qi4j" title="Source : http://qi4j.org/graphics/Qi4j-Logo-64x64.png" />
</p>
<p>La Programmation Orientée Composite (COP en anglais) pousse les concepts de la Programmation Orientée Aspects (<a href="http://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_aspect" title="Définition Wikipédia">POA</a> ou en anglais <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming" title="Définition Wikipédia">AOP</a>) dans ses retranchements en permettant de créer des objets Composites à partir de Fragments. Avec un framework de Programmation Composite il est possible d'implémenter chaque aspect comme un objet séparé puis de les traiter comme des Mixins/SideEffects/Concerns que l'on assemble en un Composite cohérent. Les principaux bénéfices d'une telle approche sont un fort découplage et une réutilisation aisée.</p></div><ul><li>lien nᵒ 1 : <a title="http://qi4j.org" hreflang="en" href="https://linuxfr.org/redirect/86114">Qi4j.org</a></li><li>lien nᵒ 2 : <a title="http://qi4j.org/downloads.html" hreflang="en" href="https://linuxfr.org/redirect/86115">Téléchargements</a></li><li>lien nᵒ 3 : <a title="http://qi4j.org/2.0" hreflang="en" href="https://linuxfr.org/redirect/86116">Documentation</a></li></ul><div><p>Qi4j reste un bon citoyen de l'écosystème Java car il est implémenté sans avoir recours à des pré-processeurs ou autre générateurs de code. Il permet d'utiliser tout ce que vous savez déjà ainsi que les outils auxquels vous êtes habitués, la liste des bibliothèques et extensions disponibles venant étayer cette affirmation.</p>
<p>Qi4j apporte donc la Programmation Orientée Composite à la plateforme Java et vous permet de rester concentrés sur le domaine métier tout en évitant la plupart des désadaptations rencontrées dans le développement logiciel comme par exemple le mapping relationel/objet, le chevauchement de différents aspects, la testabilité.</p>
<p>Les principaux points d'excellence de Qi4j sont le découpage explicite des applications en couches et modules, une approche AOP fortement typée et souple, un système d'injection basé sur les affinités, la gestion cloisonnée de la persistance, de l'indexation, de la construction de requêtes et bien d'autres choses encore.</p>
<p>D'après le co-fondateur, Niclas Hedhman, la version 2.0 est une réécriture complète du runtime. "Bien que nous ayons cassé la compatibilité en de nombreux points soigneusement sélectionnés, la plupart des applications basées sur la version 1.4 peuvent être portées avec relativement peu de changements.". Il continue en disant : "Ces changements sont nécessaires pour les prochaines fonctionnalités comme une forte intégration de Scala, du futur JDK8 et d'EventSourcing dans le modèle de persistance."</p>
<p>"La route fût longue jusqu'à la publication de cette version,", dit Paul Merlin le Release Manager pour la 2.0, "mais nous sommes convaincus que Qi4j représente la meilleure plateforme basée sur Java pour créer des applications métier."</p>
<p>Non seulement la communauté a remodelé une base de code déjà remarquable, mais elle a également produit un nouveau site web, fortement intégré avec le système de construction du framework basé sur Gradle. "Ce nouveau système permet de publier la documentation lors du processus de release." a ajouté Paul. "Tout le code présent dans la documentation est directement inclus depuis notre suite de tests. Je suis très fier du travail effectué sur le nouveau site."</p>
<p>La communauté estampille la version 2.0 "Reductionism". Qu'est-ce que cela signifie ? "Nous voulions faire tous les changements rompant la compatibilité aussi vite que possible et sortir un Qi4j le plus léger possible. Beaucoup de fonctionnalités prévues ont du attendre. Nous voulions avant tout sortir la base de la plateforme.", dit Niclas.</p>
<p>
<strong>Qu'y a-t-il de vraiment nouveau ?</strong>
</p>
<p>"Tout", dit Niclas. Pour Qi4j Core le plus important est l'introduction du paradigme fonctionnel qui permet un code plus clair. De plus, nous pourrons le porter sur le JDK8 très facilement. Le second grand changement a été de réduire la taille de Qi4j Core pour mettre plus de choses dans les Extensions comme la sérialisation et les métriques. Le nombre d'extensions pour la persistance et l'indexation a grandement augmenté.</p>
<p>
<strong>Qu'est-ce qui est prévu pour la suite ?</strong>
</p>
<p>"Nous nous concentrerons sur la productivité des développeurs. Pour les prochaines versions, nous avons à l'esprit des choses comme le support des TimeSeries et EventSourcing dans Qi4j Core, l'assemblage plus facile des Stacks d'Applications. Nous visons également à constamment enrichir le SDK (librairies, extensions, exemples et outils) ainsi que la documentation. Un autre objectif est d'agrandir la communauté en rendant plus accessible le développement du coeur de Qi4j." dit Paul. "Nous avons devant nous des chantiers importants et intéressants." ajoute Niclas.</p>
<p>La Communauté Qi4j est formée de développeurs indépendants venant d'horizons différents qui travaillent dur pour créer le framework d'applications métier le plus intéressant pour la plateforme Java.</p></div><div><a href="https://linuxfr.org/news/qi4j-sdk-2-0-framework-de-programmation-orientee-composite.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/98139/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/qi4j-sdk-2-0-framework-de-programmation-orientee-composite#comments">ouvrir dans le navigateur</a>
</p>
KaspNÿcoBenoît SibaudXavier Teyssierhttps://linuxfr.org/nodes/98139/comments.atom