<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Coffee Workshop</title>
	<atom:link href="http://blog.arkey.fr/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.arkey.fr</link>
	<description>don&#039;t waste your time</description>
	<lastBuildDate>Fri, 06 Nov 2015 20:49:05 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.5.2</generator>
	<item>
		<title>Problème de connection à Oracle</title>
		<link>https://blog.arkey.fr/2015/11/06/probleme-de-connection-a-oracle/</link>
		<comments>https://blog.arkey.fr/2015/11/06/probleme-de-connection-a-oracle/#respond</comments>
		<pubDate>Fri, 06 Nov 2015 20:33:53 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[prod]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[entropie]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[jdbc]]></category>
		<category><![CDATA[keepalive]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=493</guid>
		<description><![CDATA[Deux problèmes assez courant peuvent survenir sur les connections à une base de donnée Oracle. Ces problèmes peuvent être à l’origine de timeout sur les connections HTTP, etc… Ces deux problèmes touchent deux choses totalement différente, l’entropie du système et la coupure de connection par un firewall. Entropie Pourquoi l’entropie ? L’entropie est une mesure [&#8230;]]]></description>
				<content:encoded><![CDATA[<div class="markdown-here-wrapper" data-md-url="http://blog.arkey.fr/wp-admin/post.php?post=493&amp;action=edit">
<p style="margin: 0px 0px 1.2em !important;">Deux problèmes assez courant peuvent survenir sur les connections à une base de donnée Oracle. Ces problèmes peuvent être à l’origine de timeout sur les connections HTTP, etc…</p>
<p style="margin: 0px 0px 1.2em !important;">Ces deux problèmes touchent deux choses totalement différente, l’entropie du système et la coupure de connection par un firewall.</p>
<h2 id="entropie" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.4em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #eeeeee;">Entropie</h2>
<p style="margin: 0px 0px 1.2em !important;">Pourquoi l’entropie ? L’entropie est une mesure de l’incertitude d’un message par rapport à celui qui le précède. Sur un système POSIX c’est <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">/dev/random</code> qui est mesuré avec l’entropie. Hors la JVM utilise ce <em>device</em> pour la génération de nombres aléatoires utilisable pour des fonctions cryptographique, <a href="http://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">SecureRandom</code></a>.</p>
<p style="margin: 0px 0px 1.2em !important;">Hors le driver Oracle 11g (possiblement dans les versions précédentes aussi) établie un lien sécurisé avec la base donnée pour protéger les échanges de credentials.</p>
<p style="margin: 0px 0px 1.2em !important;">Le problème vient du fait que la lecture dans <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">/dev/random</code> est bloquante tant que le système (Linux, BSD, etc.) considère qu’il n’y a pas assez d’entropie. Heureusement en bon lecteur de la javadoc il y a une note sur <a href="http://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">SecureRandom</code></a>.</p>
<blockquote style="margin: 1.2em 0px; border-left-width: 4px; border-left-style: solid; border-left-color: #dddddd; padding: 0px 1em; color: #777777; quotes: none;">
<p style="margin: 0px 0px 1.2em !important;">Note: Depending on the implementation, the generateSeed and nextBytes methods may block as entropy is being gathered, for example, if they need to read from /dev/random on various unix-like operating systems.</p>
</blockquote>
<h3 id="la-mauvaise-solution" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.3em;">La MAUVAISE solution</h3>
<p style="margin: 0px 0px 1.2em !important;">Java permet de changer la source du random avec la propriété <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">java.security.egd</code>, si on prend le <em>device</em><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">/dev/urandom</code>. Ce device à l’inverse de <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">/dev/random</code> est non bloquant. Donc sur la ligne de comande il suffirait d’ajouter cette option pour s’en sortir ?</p>
<p></p><pre class="crayon-plain-tag">-Djava.security.egd=file:/dev/./urandom</pre><p></p>
<p style="margin: 0px 0px 1.2em !important;">Non surtout pas. Pourquoi ce n’est pas une bonne solution ? Le soucis ici est qu’on abaisse le niveau de sécurité de la JVM. Que ce soit pour l’établissement de connexion à Oracle ou une connexion HTTPS, la sécurité est compromise. Comme il n’y a plus assez d’entropie un attaquant peut connaitre ou determiner quel sera les prochains nombres qui sortiront de <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">SecureRandom</code> et donc potentiellement reconstruire les éléments cryptographiques tel que les clé privé, à partir de là l’attaquant à les mains libres.</p>
<h3 id="ce-qu-il-faut-faire" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.3em;">Ce qu’il faut faire</h3>
<p style="margin: 0px 0px 1.2em !important;">Les OS alimente <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">/dev/random</code> généralement à partir de plusieurs sources, comme les sonde de température, l’activité du CPU, le trafic réseau, mais cela s’avère parfois pas assez efficace. L’idée est donc d’aider l’OS. Installer un démon qui ajoute de l’entropie au système. Il en existe plusieurs, celui que j’utilise est <a href="http://www.issihosts.com/haveged/"><em>HAVEGED</em></a> ; il utilise les états des composants internes des processeurs modernes pour augmenter significativement l’entropie du système. À noter il tourne dans le user space donc assez facile à installer.</p>
<h2 id="avec-un-firewall" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.4em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #eeeeee;">Avec un Firewall</h2>
<p style="margin: 0px 0px 1.2em !important;">Suivant les infra et les besoins de légalité, il faut protéger les bases de données par un firewall. Le firewall va inspecter et protéger les équipements derrières mais il fait aussi de l’assainissement des connections TCP, il va couper les connections inactive au bout d’un certain temps.</p>
<h3 id="avec-le-pool-de-connection" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.3em;">Avec le pool de connection</h3>
<p style="margin: 0px 0px 1.2em !important;">En général quand on fait du connection pooling sur des connections longues (typiquement le rôle d’une Datasource) ça n’arrange pas les choses. Quand le pool donne une connection il ne sait pas forcement qu’elle à été fermé par un composant tierce (un firewall). Heureusement c’est un simple manque de configuration, il n’y a qu’à lui dire de vérifier les connections régulièrement par exemple <a href="https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html"><em>tomcat-jdbc</em></a> :</p>
<ul style="margin: 1.2em 0px; padding-left: 2em;">
<li style="margin: 0.5em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">minEvictableIdleTimeMillis</code> : The minimum amount of time an object may sit idle in the pool before it is eligible for eviction. The default value is 60000 (60 seconds).</li>
<li style="margin: 0.5em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">timeBetweenEvictionRunsMillis</code> : The number of milliseconds to sleep between runs of the idle connection validation/cleaner thread. This value should not be set under 1 second. It dictates how often we check for idle, abandoned connections, and how often we validate idle connections. The default value is 5000 (5 seconds).</li>
</ul>
<p style="margin: 0px 0px 1.2em !important;">A simple example of a datasource configuration to be adapted to your infrastructure settings.</p>
</div>
<p></p><pre class="crayon-plain-tag">&lt;Resource name="Locator"
      type="javax.sql.DataSource"
      factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
      testOnBorrow="true" driverClassName="oracle.jdbc.OracleDriver"
      validationInterval="30000"
      validationQuery="SELECT 1 FROM DUAL"
      ...
      timeBetweenEvictionRunsMillis="30000"
      minEvictableIdleTimeMillis="60000"
      url="jdbc:oracle:thin:@..."
      ...
      &gt;
&lt;/Resource&gt;</pre><p></p>
<p style="margin: 0px 0px 1.2em !important;">Certains pool offrent une configuration plus fine et peut-être plus sûre comme HirakiCP. Mais c’est hors propos. Quoiqu’il en soit cette option n’est pas optimale car elle ne traite pas le problème à sa source.</p>
<div class="markdown-here-wrapper" data-md-url="http://blog.arkey.fr/wp-admin/post.php?post=493&amp;action=edit">
<h3 id="tcp-keepalive" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.3em;">TCP Keepalive</h3>
<p style="margin: 0px 0px 1.2em !important;">TCP, le protocole réseau sur lequel transite la connection oracle, fourni un mécanisme de keepalive. Ce mécanisme va envoyer un paquet sur la connection pour que les équipements de l’infrastructure réseau dont le fameux firewall maintiennent cette connection ouverte.</p>
<p style="margin: 0px 0px 1.2em !important;">Avec Java ça se fait en passant la bonne option à l’ouverture de la socket <a href="http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_KEEPALIVE"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">SopcketOptions.SO_KEEPALIVE</code></a>. La plupart des drivers, frameworks exposent une API pour activer cette option. Avec le driver Oracle cette option s’active donc aussi.</p>
<p style="margin: 0px 0px 1.2em !important;">D’après la <a href="http://docs.oracle.com/cd/E11882_01/java.112/e16548/apxtblsh.htm#JJDBC28984">documentation Oracle</a> il y a plusieurs moyens de configurer le driver JDBC pour travailler avec un firewall.</p>
<p style="margin: 0px 0px 1.2em !important;">Dans le cas d’une configuration style <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">TNSNAMES</code> il faudra utiliser la chaine suivante <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">ENABLE=BROKEN</code> pour activer le keepalive. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">jdbc:oracle:thin:@(DESCRIPTION=(ENABLE=BROKEN)(ADDRESS=(PROTOCOL=tcp)(PORT=1521)(HOST=myhost))(CONNECT_DATA=(SID=orcl)))</pre><p></p>
<p style="margin: 0px 0px 1.2em !important;">Dans le cas d’une configuration sans <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">TNSNAMES</code> il faut passer la propriété <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">oracle.net.keepAlive</code> à <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">true</code> programmatiquement via les properties passée à l’API JDBC <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties)</code>. <em>Attention à la casse!</em> Les propriété <strong>non documentées</strong> du driver sont disponible sur la javadoc de <a href="http://download.oracle.com/otn_hosted_doc/jdeveloper/905/jdbc-javadoc/index.html?constant-values.html"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">oracle.jdbc.OracleConnection</code></a></p>
<h4 id="dans-tout-les-cas-configurer-le-keepalive-sur-l-os" style="margin: 1.3em 0px 1em; padding: 0px; font-weight: bold; font-size: 1.2em;">Dans tout les cas configurer le keepalive sur l’OS</h4>
<p style="margin: 0px 0px 1.2em !important;">Sur Linux par exemple, la <a href="http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html">documentation</a> indique comment il faut faire. Pour vérifier qu’il correspondent :</p>
<p></p><pre class="crayon-plain-tag">$ cat /proc/sys/net/ipv4/tcp_keepalive_time 
2400 
$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl 
75 
$ cat /proc/sys/net/ipv4/tcp_keepalive_probes 
6</pre><p></p>
<p style="margin: 0px 0px 1.2em !important;">Ces paramètres disent la pile TCP enverra la première sonde (premier paquet de keepalive) au bout de 40min, attendra 75 millisecondes avant de renvoyer une sonde dans la limite de 6 essais. Si aucun ACK n’est reçu alors la connection est reconnue par l’OS comme fermée.</p>
<p style="margin: 0px 0px 1.2em !important;">Quoiqu’il en soit il faut régler ces paramètres en accord avec les réglages des équipement réseau.</p>
<p style="margin: 0px 0px 1.2em !important;"><em>À noter que la documention indique bien que le keepalive est un comportement à activer volontairement, d’ou l’option <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; border-radius: 3px; display: inline; background-color: #f8f8f8;">SopcketOptions.SO_KEEPALIVE</code> dans la JVM.</em></p>
<blockquote style="margin: 1.2em 0px; border-left-width: 4px; border-left-style: solid; border-left-color: #dddddd; padding: 0px 1em; color: #777777; quotes: none;">
<p style="margin: 0px 0px 1.2em !important;">Remember that keepalive support, even if configured in the kernel, is not the default behavior in Linux. Programs must request keepalive control for their sockets using the setsockopt interface.</p>
</blockquote>
</div>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2015/11/06/probleme-de-connection-a-oracle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Générer le script DDL programmatiquement avec Hibernate 4.x</title>
		<link>https://blog.arkey.fr/2015/08/07/generer-le-script-ddl-programmatiquement-avec-hibernate-4-x/</link>
		<comments>https://blog.arkey.fr/2015/08/07/generer-le-script-ddl-programmatiquement-avec-hibernate-4-x/#respond</comments>
		<pubDate>Fri, 07 Aug 2015 13:26:51 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[ddl]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java8]]></category>
		<category><![CDATA[jpa]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=482</guid>
		<description><![CDATA[Si par hasard votre base donnée est gérée par un véritable DBA, donc avec des scripts SQL. Mais que vous utilisez hibernate pour mapper les tables avec une configuration non triviale, modules bien découpés, package annotés, etc&#8230;. Les utilitaires comme hibernate4-maven-plugin ne suffisent plus. Voici un petit exemple code qui utilise le SchemaExporter de hibernate. Le code [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Si par hasard votre base donnée est gérée par un véritable DBA, donc avec des scripts SQL. Mais que vous utilisez hibernate pour mapper les tables avec une configuration non triviale, modules bien découpés, package annotés, etc&#8230;. Les utilitaires comme <em><a href="http://juplo.de/hibernate4-maven-plugin/">hibernate4-maven-plugin</a></em> ne suffisent plus.</p>
<p>Voici un petit exemple code qui utilise le <code>SchemaExporter</code> de hibernate. <em>Le code est bien sûr à adapter à la structure du code de l&#8217;application</em>.</p>
<p>Le principe est de passer soit même les classes annotées ET les package annotés (typiquement par <code>@TypeDef</code> dans le <code>package-info.java</code>). Pour plus de commodité ce code utilise le framework <a href="https://github.com/ronmamo/reflections">Reflections</a> pour scanner les classes annotées par les annotations JPA <code>@Entity</code> et <code>@MappedSuperClass</code>. Par défaut le script génère les <code>drop statements</code>, mais ce comportement peut se changer à travers les options de <code>SchemaExport</code>.</p>
<p></p><pre class="crayon-plain-tag">import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.Target;
import org.junit.Test;
import org.reflections.Reflections;

public class HibernateDDLGenerator {

    public static final String ENTITIES_PACKAGE = &quot;com.something&quot;;
    public static final String ANNOTATED_PACKAGE = &quot;com&quot;;
    public static final String HBM_DIALECT = &quot;org.hibernate.dialect.Oracle10gDialect&quot;;

    @Test
    public void ddl() throws Exception {
        new SchemaExport(createHibernateConfig())
                .setOutputFile(&quot;/tmp/ddl.sql&quot;)
                .setFormat(true)
                .setDelimiter(&quot;;&quot;)
                .create(Target.EXPORT);
    }

    private Configuration createHibernateConfig() {

        Configuration conf = new Configuration();

        final Reflections reflections = new Reflections(ENTITIES_PACKAGE);
        reflections.getTypesAnnotatedWith(MappedSuperclass.class).forEach(conf::addAnnotatedClass);
        reflections.getTypesAnnotatedWith(Entity.class).forEach(conf::addAnnotatedClass);

        conf.addPackage(ANNOTATED_PACKAGE) // contains @TypeDefs
            .setProperty(AvailableSettings.DIALECT, HBM_DIALECT);
        return conf;
    }
}</pre><p></p>
<p>gist : https://gist.github.com/bric3/370654ecad0eb81aca22</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2015/08/07/generer-le-script-ddl-programmatiquement-avec-hibernate-4-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Note pour plus tard: Problème avec jVisualVM sur OSX</title>
		<link>https://blog.arkey.fr/2012/10/10/note-pour-tard-quand-jvisualvm-ne-marche-pas-sur-sur-osx/</link>
		<comments>https://blog.arkey.fr/2012/10/10/note-pour-tard-quand-jvisualvm-ne-marche-pas-sur-sur-osx/#respond</comments>
		<pubDate>Wed, 10 Oct 2012 10:25:57 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[tips]]></category>
		<category><![CDATA[heap dump]]></category>
		<category><![CDATA[instrumentation]]></category>
		<category><![CDATA[jdk7]]></category>
		<category><![CDATA[jmap]]></category>
		<category><![CDATA[jmx]]></category>
		<category><![CDATA[jstack]]></category>
		<category><![CDATA[jvisualvm]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[mountain lion]]></category>
		<category><![CDATA[thread dump]]></category>
		<category><![CDATA[visualvm]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=451</guid>
		<description><![CDATA[Au cour d&#8217;un petit development, j&#8217;ai remarqué que mon process ne se terminait pas, une fois l&#8217;exécution de mon code terminé. Il devait y avoir soit une thread qui tournait encore, soit un deadlock quelque part, j&#8217;optais plus pour la seconde option. Du coup je lance jvisualvm depuis mon terminal (celui du JDK7 update 7). [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Au cour d&#8217;un petit development, j&#8217;ai remarqué que mon process ne se terminait pas, une fois l&#8217;exécution de mon code terminé. Il devait y avoir soit une thread qui tournait encore, soit un deadlock quelque part, j&#8217;optais plus pour la seconde option.</p>
<p>Du coup je lance <code>jvisualvm</code> depuis mon terminal (celui du JDK7 update 7). Là j&#8217;ai la liste des process java qui tournent malheureusement quand je choisi d&#8217;investiguer ce process, <code>jvisualvm</code> me rapporte sur le terminal :</p><pre class="crayon-plain-tag">attach: task_for_pid(7234) failed (5)</pre><p>L&#8217;onglet du process s&#8217;ouvre bien dans <code>jvisualvm</code> mais impossible monitorer les threads ni faire de heap dump (au cas ou ça m&#8217;intéresserai), d&#8217;ailleurs ces sous-onglets ne sont même pas affiché.</p>
<p>La solution: passer avant au process java qu&#8217;il faut monitorer les paramètres suivants (en fonction des besoins)</p>
<ul>
<li><code><strong>-Xverify:none</strong></code> : Désactive la vérification du bytecode dans la JVM. De base la JVM s&#8217;assure que le bytecode vérifie certaines règles. Bref il faut activer ce flag si vous voulez faire des thread dump ou des heap dump. Il s&#8217;agit probablement d&#8217;un bug du JDK7 ou de jVisualVM sur OSX.</li>
<li><code><strong>-Xshare:off</strong></code> : Comme son nom l&#8217;indique il s&#8217;agit de partager de la mémoire, dans les faits ça se traduit par le partage des classes déjà chargé. Sur mac cette option est active par défaut. A priori cette option pose problème pour l&#8217;attachement à un process Java, du coup en isolant la mémoire du process on peut s&#8217;en sortir.</li>
<li><code><strong>-Dcom.sun.management.jmxremote</strong></code> : Active l&#8217;export des MBean de la JVM, si vous voulez les monitorer</li>
</ul>
<p>On dirait une réapparition dans le JDK7u7 d&#8217;un bug a priori déjà clos dans le JDK6 (pour OSX). A noter que les outils en ligne de commade tel que <code>jmap</code> peuvent aussi être affectés.</p>
<p>Bien entendu si j&#8217;ai loupé un truc je suis tout ouïe.</p>
<p>Référence : <a href="http://java.net/jira/browse/VISUALVM-326">http://java.net/jira/browse/VISUALVM-326</a></p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2012/10/10/note-pour-tard-quand-jvisualvm-ne-marche-pas-sur-sur-osx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caliper me : Ou pourquoi les microbenchmarks aident !</title>
		<link>https://blog.arkey.fr/2012/08/29/caliper-ou-pourquoi-les-microbenchmarks-aident/</link>
		<comments>https://blog.arkey.fr/2012/08/29/caliper-ou-pourquoi-les-microbenchmarks-aident/#comments</comments>
		<pubDate>Tue, 28 Aug 2012 22:47:50 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[big o]]></category>
		<category><![CDATA[cailper]]></category>
		<category><![CDATA[complexity]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[measure]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[metrics]]></category>
		<category><![CDATA[microbenchmark]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=362</guid>
		<description><![CDATA[Contexte Dans les news récemment Guava 13.0 réduit la consommation en mémoire de plusieurs structures [source] J&#8217;ai passé des tests d&#8217;algorithmie [source] Premier point, on sait que Google est attentif sur les performances de ses librairies. Sur le deuxième point, ben j&#8217;ai finalement loupé un des exercices &#8220;timeboxés&#8221;, je n&#8217;ai pas eu le temps de [&#8230;]]]></description>
				<content:encoded><![CDATA[<h1>Contexte</h1>
<p>Dans les news récemment</p>
<ul>
<li>Guava 13.0 réduit la consommation en mémoire de plusieurs structures [<a title="Guava 13.0 release notes" href="http://code.google.com/p/guava-libraries/wiki/Release13">source</a>]</li>
<li>J&#8217;ai passé des tests d&#8217;algorithmie [<a href="#">source</a>]</li>
</ul>
<p>Premier point, on sait que Google est attentif sur les performances de ses librairies. Sur le deuxième point, ben j&#8217;ai finalement loupé un des exercices &#8220;timeboxés&#8221;, je n&#8217;ai pas eu le temps de le finir a temps, du coup le code soumis était 100 % foireux. Mais bon ce n&#8217;est pas le sujet du billet, ce qui est important c&#8217;est que j&#8217;ai fini après cet algo, puis je me suis rendu compte que celui-ci n&#8217;était pas optimal, il ressemblait à un algo en <del>O(n<sup>2</sup>)</del> O(n log n) (<a href="#comment-834"><em>Merci Sam pour cette correction</em></a>). Du coup j&#8217;ai repris le papier et le crayon, et je me suis rendu compte que je pouvais utiliser une technique similaire à celle que j&#8217;ai utilisé sur le premier algo du test (comment n&#8217;ai-je pas pu y penser à ce moment d&#8217;ailleurs ?).</p>
<p>De mémoire l&#8217;algo porte grosso modo sur le comptage de paires d&#8217;entier distante d&#8217;un nombre K dans un tableau A.</p>
<p>Ma première version :</p><pre class="crayon-plain-tag">class PairCounts_V1 {
    public int countPairsWithKDistance(int K, int[] A) {
        if(A == null || A.length &lt; 2) return 0;

        Arrays.sort(A);

        int paircounter = 0;

        int j = A.length - 1;
        for (int i = 0; i &lt;= j; i++) {
            int val_i = A[i];

            for(; i&lt;j &amp;&amp; K - A[j] != val_i; j--);
            int val_j = A[j];

            if ((long) (val_i + val_j) == K) {
                paircounter = incrementPairCounter(paircounter, i, j);

                // count duplicates
                while(val_j == A[--j]) paircounter =
                              incrementPairCounter(paircounter, i, j);
            }
            j = A.length-1;
        }

        return kpaircounter;
    }

    private int incrementPairCounter(int paircounter, int i, int j) {
        paircounter++;
        if(i != j ) paircounter++;
        return paircounter;
    }
}</pre><p>Alors pourquoi je pense que cet algo n&#8217;est pas optimal : simplement du fait des boucles inbriquée, on dirait du <del>O(n<sup>2</sup>)</del> O(n log n) (<em><a href="#comment-834">voir ici pourquoi</a></em>). Mais quand on parle de la performance ou de la complexité d&#8217;un algorithme il ne faut prendre uniquement compte de l&#8217;invariant mais aussi <strong>du jeu de données : quelle taille ? quelle distribution ? quel type de données ?</strong></p>
<p>En effet un algorithme pour être efficace doit être adapté aux jeux de données qu&#8217;il aura à traiter et à l&#8217;usage qu&#8217;on en a ; peut-être à travers des paramètres ou des structures différentes, typiquement un des constructeur d&#8217;une HashMap prend des paramètres comme <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html#HashMap(int, float)">le facteur de charge et la taille initiale</a>, on pourra choisir une <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/util/TreeMap.html">TreeMap</a> au lieu d&#8217;une <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html">HashMap</a> si la recherche est un cas d&#8217;utilisation de la structure de donnée.</p>
<p>Bref du coup voilà à quoi ressemble la nouvelle version de cet algo :</p><pre class="crayon-plain-tag">class PairCounts_V2 {

public int countPairsWithKDistance(int K, int[] A) {
        if(A == null || A.length &lt; 2) return 0;

        HashMap&lt;Long, Integer&gt; complements = new HashMap&lt;Long, Integer&gt;();
        for (int number : A) {
            long complement = K - number;

            Integer complementCount = complements.get(complement);
            complementCount = complementCount == null ?
                                  Integer.valueOf(1)
                                  : ++complementCount;
            complements.put(complement, complementCount);
        }

        int paircounter = 0;
        for (int number : A) {
            Long key = Long.valueOf(number);
            Integer complementCount = complements.get(key);
            paircounter = complementCount == null ?
                              paircounter
                              : paircounter + complementCount;
        }

        return paircounter;
    }

}</pre><p>Donc ici l&#8217;idée c&#8217;est de préparer dans un premier temps un dictionnaire  inversé basé sur un des entier et la distance demandée, en incrémentant pour chaque occurence. Ici une seule boucle for, car on parcours en entier le tableau. Dans un second temps on cherche les entiers qui correspondent effectivement à l&#8217;entrée de ce dictionnaire, et si oui on incrémente le compteur de paires. Là aussi une seule boucle sur le tableau donc O(n). Sachant qu&#8217;une HashMap a souvant une complexité de O(1) pour l&#8217;insertion et la recherche, a vue de nez l&#8217;algo est plutot pas mal.</p>
<p>Bon mais dans la réalité ca donne quoi, en effet comme Kirk Pepperdine et bien d&#8217;autres disaient : <em><strong>Measure ! Don&#8217;t guess !</strong></em></p>
<h1>Caliper me voilà !</h1>
<p><a href="http://code.google.com/p/caliper/">Caliper</a> est un outil codé par des personnes de chez Google, il est notamment utilisé par l&#8217;équipe en charge de Guava. On peut d&#8217;ailleurs voir dans les sources de Guava les benchmarks <a href="http://code.google.com/p/guava-libraries/source/browse/#git%2Fguava-tests%2Fbenchmark%2Fcom%2Fgoogle%2Fcommon%2Fcollect">ici</a> par exemple.</p>
<p>Avec un projet &#8220;mavenisé&#8221; on récupère la dernière version de <strong>caliper</strong>, la version <strong>0.5-rc1</strong> aujourd&#8217;hui.</p><pre class="crayon-plain-tag">&lt;dependency&gt;
    &lt;groupid&gt;com.google.caliper&lt;/groupid&gt;
    &lt;artifactid&gt;caliper&lt;/artifactid&gt;
    &lt;version&gt;0.5-rc1&lt;/version&gt;
&lt;/dependency&gt;</pre><p>Pour écrire un benchmark caliper il suffit d&#8217;étendre la classe <code><a href="http://caliper.googlecode.com/svn/static/api/reference/com/google/caliper/SimpleBenchmark.html"><strong>SimpleBenchmark</strong></a></code>, puis d&#8217;écrire des méthodes <code>public int</code> avec le préfixe <code>times</code> et un paramètre <code>répétition</code> utilisé dans une boucle <code>for</code>. Pour passer des paramètres particuliers au benchmark on utilisera un ou des champs annoté(s) par <code><a href="http://caliper.googlecode.com/svn/static/api/reference/com/google/caliper/Param.html">@Param</a></code>.</p>
<p>Enfin comme Caliper lance une nouvelle VM, fait quelques travaux pour chauffer la VM (warmup), etc, il faut pour l&#8217;instant lancer ces tests avec une commande manuelle :</p><pre class="crayon-plain-tag">java -classpath $THE_CLASSPATH com.google.caliper.Runner PairCountsBenchmark</pre><p>La ligne de commande pourra varier suivant les besoins ; on peut notamment se rendre sur leur site pour y voir les <a href="http://code.google.com/p/caliper/wiki/CommandLineOptions">options</a> (le lien wiki est à ce jour en retard par rapport au <a href="http://code.google.com/p/caliper/source/browse/caliper/src/main/java/com/google/caliper/Runner.java?name=v0.5-rc1">code</a>) à passer au <code>Runner</code> Caliper. Malgré la jeunesse du framework sa documentation parfois spartiate, le projet a de réelles forces et s&#8217;avère de plus en plus populaire dans le domaine. Bien que le développement de ce projet avance lentement, ce projet est aujourd&#8217;hui maintenu par des membres de l&#8217;équipe Guava.</p>
<p>Donc le benchmark que j&#8217;ai mis en place :</p><pre class="crayon-plain-tag">public class PairCountsBenchmark extends SimpleBenchmark {

    @Param({ "1", "6", "25", "7", "111111111" }) private int K;  // différentes valeurs de la distance de la paire
    @Param({"10", "100", "1000", "10000"}) private int length;   // différentes tailles du tableau d'entier

    @Param private Distribution distribution;                    // Type de distribution SAWTOOTH, RANDOM, une autre

    private int[] values;

    @Override protected void setUp() throws Exception {          // Création du tableau d'entier
        values = distribution.create(length);
    }

    public int timePairCounts_V1(int repetition) {
        int dummy = 0;
        for (int i = 0; i &lt; repetition; i++) {
            dummy += new PairCounts_V1().complementary_pairs(K, values);
        }
        return dummy;                                            // Variable modifiée dans la boucle pour forcer la JVM a ne pas supprimer cette boucle for.
    }

    public int timePairCounts_V2(int repetition) {
        int dummy = 0;
        for (int i = 0; i &lt; repetition; i++) {
            dummy += new PairCounts_V2().complementary_pairs(K, values);
        }
        return dummy;
    }

    public enum Distribution {                                   // Le code de la distribution voulue
        SAWTOOTH {
            @Override
            int[] create(int length) {
                int[] result = new int[length];
                for (int i = 0; i &lt; length; i += 5) {
                    result[i] = 0;
                    result[i + 1] = 1;
                    result[i + 2] = 2;
                    result[i + 3] = 3;
                    result[i + 4] = 4;
                }
                return result;
            }
        },
        RANDOM {
            @Override
            int[] create(int length) {
                Random random = new Random();
                int[] result = new int[length];
                for (int i = 0; i &lt; length; i++) {
                    result[i] = random.nextInt();
                }
                return result;
            }
        };

        abstract int[] create(int length);
    }
}</pre><p></p>
<h2>Dans le temps</h2>
<p>Voilà il faut maintenant lancer le benchmark en ligne de commande. Et voici une partie de la sortie standard :</p><pre class="crayon-plain-tag">0% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=10} 117.03 ns; σ=0.53 ns @ 3 trials
 1% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=10} 410.92 ns; σ=3.93 ns @ 5 trials
 3% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=10} 118.95 ns; σ=0.54 ns @ 3 trials
 4% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=10} 346.11 ns; σ=1.04 ns @ 3 trials
 5% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=10} 124.75 ns; σ=0.42 ns @ 3 trials
 6% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=10} 343.76 ns; σ=0.60 ns @ 3 trials
 8% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=10} 116.55 ns; σ=0.11 ns @ 3 trials
 9% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=10} 340.24 ns; σ=0.88 ns @ 3 trials
10% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=10} 124.34 ns; σ=1.17 ns @ 8 trials
11% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=10} 375.23 ns; σ=2.22 ns @ 3 trials
13% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=10} 120.60 ns; σ=0.56 ns @ 3 trials
14% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=10} 399.89 ns; σ=6.66 ns @ 10 trials
15% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=10} 122.83 ns; σ=0.50 ns @ 3 trials
16% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=10} 405.20 ns; σ=6.81 ns @ 10 trials
18% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=10} 121.31 ns; σ=0.82 ns @ 3 trials
19% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=10} 406.40 ns; σ=7.90 ns @ 10 trials
20% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=10} 123.25 ns; σ=0.44 ns @ 3 trials
21% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=10} 403.80 ns; σ=4.77 ns @ 10 trials
23% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=10} 122.23 ns; σ=0.95 ns @ 3 trials
24% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=10} 401.21 ns; σ=9.94 ns @ 10 trials
25% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=100} 3554.64 ns; σ=13.22 ns @ 3 trials
26% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=100} 3353.02 ns; σ=28.50 ns @ 4 trials
28% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=100} 3616.36 ns; σ=23.17 ns @ 3 trials
29% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=100} 2759.35 ns; σ=7.49 ns @ 3 trials
30% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=100} 3230.40 ns; σ=6.89 ns @ 3 trials
31% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=100} 2630.14 ns; σ=11.76 ns @ 3 trials
33% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=100} 3470.91 ns; σ=21.03 ns @ 3 trials
34% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=100} 2703.77 ns; σ=2.87 ns @ 3 trials
35% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=100} 3237.29 ns; σ=31.98 ns @ 3 trials
36% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=100} 3462.79 ns; σ=14.26 ns @ 3 trials
38% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=100} 3664.38 ns; σ=22.84 ns @ 3 trials
39% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=100} 4782.95 ns; σ=21.09 ns @ 3 trials
40% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=100} 3666.78 ns; σ=11.56 ns @ 3 trials
41% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=100} 4829.99 ns; σ=18.42 ns @ 3 trials
43% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=100} 3669.01 ns; σ=3.86 ns @ 3 trials
44% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=100} 4800.20 ns; σ=27.45 ns @ 3 trials
45% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=100} 3697.72 ns; σ=16.69 ns @ 3 trials
46% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=100} 4867.33 ns; σ=39.87 ns @ 3 trials
48% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=100} 3663.00 ns; σ=18.92 ns @ 3 trials
49% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=100} 4792.09 ns; σ=23.93 ns @ 3 trials
50% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=1000} 253205.17 ns; σ=2409.40 ns @ 3 trials
51% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=1000} 28733.38 ns; σ=57.50 ns @ 3 trials
53% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=1000} 252201.82 ns; σ=1916.34 ns @ 3 trials
54% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=1000} 26003.20 ns; σ=79.01 ns @ 3 trials
55% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=1000} 254835.90 ns; σ=1142.59 ns @ 3 trials
56% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=1000} 24830.33 ns; σ=96.51 ns @ 3 trials
57% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=1000} 336495.11 ns; σ=3182.70 ns @ 3 trials
59% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=1000} 25425.31 ns; σ=236.34 ns @ 4 trials
60% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=1000} 254613.30 ns; σ=591.19 ns @ 3 trials
61% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=1000} 31176.21 ns; σ=34.10 ns @ 3 trials
63% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=1000} 264752.16 ns; σ=1911.17 ns @ 3 trials
64% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=1000} 53425.63 ns; σ=530.29 ns @ 5 trials
65% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=1000} 268841.98 ns; σ=1489.84 ns @ 3 trials
66% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=1000} 58635.35 ns; σ=387.69 ns @ 3 trials
68% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=1000} 266655.10 ns; σ=1012.10 ns @ 3 trials
69% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=1000} 59015.10 ns; σ=814.55 ns @ 10 trials
70% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=1000} 268504.45 ns; σ=482.22 ns @ 3 trials
71% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=1000} 58601.33 ns; σ=568.63 ns @ 3 trials
73% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=1000} 265022.05 ns; σ=1939.79 ns @ 3 trials
74% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=1000} 58487.85 ns; σ=587.15 ns @ 10 trials
75% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=10000} 23462428.57 ns; σ=79476.07 ns @ 3 trials
76% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=10000} 285100.65 ns; σ=3403.03 ns @ 10 trials
78% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=10000} 42566217.39 ns; σ=189344.42 ns @ 3 trials
79% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=10000} 273497.95 ns; σ=2738.46 ns @ 7 trials
80% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=10000} 24271754.10 ns; σ=74440.46 ns @ 3 trials
81% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=10000} 257143.69 ns; σ=1045.68 ns @ 3 trials
83% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=10000} 33062666.67 ns; σ=154823.32 ns @ 3 trials
84% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=10000} 270617.53 ns; σ=1484.45 ns @ 3 trials
85% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=10000} 24082112.90 ns; σ=67162.43 ns @ 3 trials
86% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=10000} 296935.84 ns; σ=197.58 ns @ 3 trials
88% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=10000} 24617137.50 ns; σ=222519.79 ns @ 4 trials
89% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=10000} 837504.04 ns; σ=7730.54 ns @ 4 trials
90% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=10000} 24380700.00 ns; σ=28021.86 ns @ 3 trials
91% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=10000} 861687.14 ns; σ=7389.43 ns @ 3 trials
93% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=10000} 24449950.00 ns; σ=137734.32 ns @ 3 trials
94% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=10000} 865862.78 ns; σ=6500.68 ns @ 3 trials
95% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=10000} 24474200.00 ns; σ=49916.49 ns @ 3 trials
96% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=10000} 860750.64 ns; σ=8304.85 ns @ 6 trials
98% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=10000} 24364925.00 ns; σ=72881.36 ns @ 3 trials
99% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=10000} 840977.96 ns; σ=8104.18 ns @ 10 trials

    benchmark length distribution         K       ns linear runtime
PairCounts_V1     10     SAWTOOTH         1      117 =
PairCounts_V1     10     SAWTOOTH         6      119 =
PairCounts_V1     10     SAWTOOTH        25      125 =
PairCounts_V1     10     SAWTOOTH         7      117 =
PairCounts_V1     10     SAWTOOTH 111111111      124 =
PairCounts_V1     10       RANDOM         1      121 =
PairCounts_V1     10       RANDOM         6      123 =
PairCounts_V1     10       RANDOM        25      121 =
PairCounts_V1     10       RANDOM         7      123 =
PairCounts_V1     10       RANDOM 111111111      122 =
PairCounts_V1    100     SAWTOOTH         1     3555 =
PairCounts_V1    100     SAWTOOTH         6     3616 =
PairCounts_V1    100     SAWTOOTH        25     3230 =
PairCounts_V1    100     SAWTOOTH         7     3471 =
PairCounts_V1    100     SAWTOOTH 111111111     3237 =
PairCounts_V1    100       RANDOM         1     3664 =
PairCounts_V1    100       RANDOM         6     3667 =
PairCounts_V1    100       RANDOM        25     3669 =
PairCounts_V1    100       RANDOM         7     3698 =
PairCounts_V1    100       RANDOM 111111111     3663 =
PairCounts_V1   1000     SAWTOOTH         1   253205 =
PairCounts_V1   1000     SAWTOOTH         6   252202 =
PairCounts_V1   1000     SAWTOOTH        25   254836 =
PairCounts_V1   1000     SAWTOOTH         7   336495 =
PairCounts_V1   1000     SAWTOOTH 111111111   254613 =
PairCounts_V1   1000       RANDOM         1   264752 =
PairCounts_V1   1000       RANDOM         6   268842 =
PairCounts_V1   1000       RANDOM        25   266655 =
PairCounts_V1   1000       RANDOM         7   268504 =
PairCounts_V1   1000       RANDOM 111111111   265022 =
PairCounts_V1  10000     SAWTOOTH         1 23462429 ================
PairCounts_V1  10000     SAWTOOTH         6 42566217 ==============================
PairCounts_V1  10000     SAWTOOTH        25 24271754 =================
PairCounts_V1  10000     SAWTOOTH         7 33062667 =======================
PairCounts_V1  10000     SAWTOOTH 111111111 24082113 ================
PairCounts_V1  10000       RANDOM         1 24617138 =================
PairCounts_V1  10000       RANDOM         6 24380700 =================
PairCounts_V1  10000       RANDOM        25 24449950 =================
PairCounts_V1  10000       RANDOM         7 24474200 =================
PairCounts_V1  10000       RANDOM 111111111 24364925 =================
PairCounts_V2     10     SAWTOOTH         1      411 =
PairCounts_V2     10     SAWTOOTH         6      346 =
PairCounts_V2     10     SAWTOOTH        25      344 =
PairCounts_V2     10     SAWTOOTH         7      340 =
PairCounts_V2     10     SAWTOOTH 111111111      375 =
PairCounts_V2     10       RANDOM         1      400 =
PairCounts_V2     10       RANDOM         6      405 =
PairCounts_V2     10       RANDOM        25      406 =
PairCounts_V2     10       RANDOM         7      404 =
PairCounts_V2     10       RANDOM 111111111      401 =
PairCounts_V2    100     SAWTOOTH         1     3353 =
PairCounts_V2    100     SAWTOOTH         6     2759 =
PairCounts_V2    100     SAWTOOTH        25     2630 =
PairCounts_V2    100     SAWTOOTH         7     2704 =
PairCounts_V2    100     SAWTOOTH 111111111     3463 =
PairCounts_V2    100       RANDOM         1     4783 =
PairCounts_V2    100       RANDOM         6     4830 =
PairCounts_V2    100       RANDOM        25     4800 =
PairCounts_V2    100       RANDOM         7     4867 =
PairCounts_V2    100       RANDOM 111111111     4792 =
PairCounts_V2   1000     SAWTOOTH         1    28733 =
PairCounts_V2   1000     SAWTOOTH         6    26003 =
PairCounts_V2   1000     SAWTOOTH        25    24830 =
PairCounts_V2   1000     SAWTOOTH         7    25425 =
PairCounts_V2   1000     SAWTOOTH 111111111    31176 =
PairCounts_V2   1000       RANDOM         1    53426 =
PairCounts_V2   1000       RANDOM         6    58635 =
PairCounts_V2   1000       RANDOM        25    59015 =
PairCounts_V2   1000       RANDOM         7    58601 =
PairCounts_V2   1000       RANDOM 111111111    58488 =
PairCounts_V2  10000     SAWTOOTH         1   285101 =
PairCounts_V2  10000     SAWTOOTH         6   273498 =
PairCounts_V2  10000     SAWTOOTH        25   257144 =
PairCounts_V2  10000     SAWTOOTH         7   270618 =
PairCounts_V2  10000     SAWTOOTH 111111111   296936 =
PairCounts_V2  10000       RANDOM         1   837504 =
PairCounts_V2  10000       RANDOM         6   861687 =
PairCounts_V2  10000       RANDOM        25   865863 =
PairCounts_V2  10000       RANDOM         7   860751 =
PairCounts_V2  10000       RANDOM 111111111   840978 =

vm: java
trial: 0

Process finished with exit code 0</pre><p>Donc en fait Caliper créé une matrice multi-dimensionnelle des différents paramètres et pour chaque coordonnée dans cette matrice lance le test, bref un Scénario.</p>
<p>On voit dans les mesures faites par Caliper le temps pris par chaque méthode, l&#8217;écart type, et le nombre d&#8217;essai. Enfin dans une deuxième partie Caliper donne un synopsis des différents run et en particulier une colonne très intéressante &#8216;<strong>linear time</strong>&#8216;.</p>
<p>En observant le temps pris en fonction du nombre d&#8217;éléments pour chaque algo, on s&#8217;aperçoit que le temps pris par le premier algo augmente en effet par rapport au deuxième algo d&#8217;un facteur 5 qui augmente avec la taille du tableau. Bref on est loin d&#8217;un temps linéaire aka O(n).</p>
<p>Ce qui est aussi intéressant, c&#8217;est que le premier algo est plus efficace tant que le nombre d&#8217;élément dans le tableau d&#8217;entrée est inférieur à 100. Alors que la deuxième  qui utilise une structure plus élaboré ne montre des signes avantageux qu&#8217;à partir d&#8217;une centaine d&#8217;éléments. Ca me rappelle étrangement l&#8217;électronique ou les comportements des capacités et inductances changeant de nature lorsqu&#8217;on passe en haute fréquence.</p>
<h2>Dans l&#8217;espace</h2>
<p>Alors pour faire les mesures des allocations, on peut aussi utiliser caliper, mais à l&#8217;heure de l&#8217;écriture de ce blog, il faut faire quelques petites choses en plus.</p>
<ol>
<li>Caliper 0.5 RC1 vient avec le jar <code>java-allocation-instrumenter-2.0.jar</code> qui est sensé servir d&#8217;agent, cependant ce jar n&#8217;a pas été généré correctement pour servir d&#8217;agent. En fait il faut télécharger le jar <code>allocation.jar</code> de ce projet : <a href="http://code.google.com/p/java-allocation-instrumenter/">http://code.google.com/p/java-allocation-instrumenter/</a> daté du <a href="http://code.google.com/p/java-allocation-instrumenter/downloads/detail?name=allocation.jar&amp;can=2&amp;q=">1 er février 2012</a>.</li>
<li>Avant de lancer le Runner en ligne de commande il faut ajouter la variable d&#8217;environnement <code>ALLOCATION_JAR</code><br />
<pre class="crayon-plain-tag">export ALLOCATION_JAR=/path/to/downloaded/allocation.jar</pre>
</li>
<li>Enfin il est possible de lancer le même benchmark avec des tests sur la mémoire :<br />
<pre class="crayon-plain-tag">java -classpath $THE_CLASSPATH --measureMemory com.google.caliper.Runner PairCountsBenchmark</pre>
</li>
</ol>
<p>&nbsp;</p>
<blockquote><p>A noter : Ne pas renommer <code>allocation.jar</code> en autre chose, sans ça vous n&#8217;aurez pas d&#8217;instrumentation !</p></blockquote>
<p>Ce qui donne le résultat suivant, quasiment la même chose, mais avec les infos sur les allocations mémoire.</p><pre class="crayon-plain-tag">0% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=10} 119.06 ns; σ=1.08 ns @ 5 trials, allocated 1 instances for a total of 16B
 1% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=10} 468.80 ns; σ=4.56 ns @ 3 trials, allocated 9 instances for a total of 320B
 3% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=10} 115.83 ns; σ=0.46 ns @ 3 trials, allocated 1 instances for a total of 16B
 4% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=10} 426.45 ns; σ=3.65 ns @ 3 trials, allocated 9 instances for a total of 320B
 5% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=10} 125.06 ns; σ=0.52 ns @ 3 trials, allocated 1 instances for a total of 16B
 6% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=10} 407.38 ns; σ=1.42 ns @ 3 trials, allocated 9 instances for a total of 320B
 8% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=10} 116.38 ns; σ=1.11 ns @ 6 trials, allocated 1 instances for a total of 16B
 9% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=10} 425.28 ns; σ=0.46 ns @ 3 trials, allocated 9 instances for a total of 320B
10% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=10} 125.12 ns; σ=0.18 ns @ 3 trials, allocated 1 instances for a total of 16B
11% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=10} 439.33 ns; σ=3.29 ns @ 3 trials, allocated 19 instances for a total of 560B
13% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=10} 121.67 ns; σ=0.46 ns @ 3 trials, allocated 1 instances for a total of 16B
14% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=10} 482.23 ns; σ=3.74 ns @ 3 trials, allocated 34 instances for a total of 960B
15% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=10} 120.69 ns; σ=0.71 ns @ 3 trials, allocated 1 instances for a total of 16B
16% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=10} 455.67 ns; σ=3.55 ns @ 3 trials, allocated 34 instances for a total of 960B
18% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=10} 121.64 ns; σ=0.42 ns @ 3 trials, allocated 1 instances for a total of 16B
19% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=10} 464.34 ns; σ=7.45 ns @ 10 trials, allocated 34 instances for a total of 960B
20% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=10} 120.85 ns; σ=0.38 ns @ 3 trials, allocated 1 instances for a total of 16B
21% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=10} 454.11 ns; σ=5.22 ns @ 10 trials, allocated 34 instances for a total of 960B
23% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=10} 122.14 ns; σ=1.12 ns @ 4 trials, allocated 1 instances for a total of 16B
24% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=10} 481.91 ns; σ=7.18 ns @ 10 trials, allocated 34 instances for a total of 960B
25% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=100} 3530.68 ns; σ=18.40 ns @ 3 trials, allocated 1 instances for a total of 16B
26% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=100} 3095.60 ns; σ=7.39 ns @ 3 trials, allocated 9 instances for a total of 320B
28% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=100} 3677.07 ns; σ=36.07 ns @ 3 trials, allocated 1 instances for a total of 16B
29% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=100} 2871.70 ns; σ=96.87 ns @ 10 trials, allocated 9 instances for a total of 320B
30% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=100} 3253.18 ns; σ=16.46 ns @ 3 trials, allocated 1 instances for a total of 16B
31% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=100} 2830.61 ns; σ=61.72 ns @ 10 trials, allocated 9 instances for a total of 320B
33% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=100} 3868.67 ns; σ=36.13 ns @ 3 trials, allocated 1 instances for a total of 16B
34% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=100} 2747.84 ns; σ=26.29 ns @ 3 trials, allocated 9 instances for a total of 320B
35% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=100} 3240.13 ns; σ=12.72 ns @ 3 trials, allocated 1 instances for a total of 16B
36% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=100} 2941.78 ns; σ=39.47 ns @ 10 trials, allocated 109 instances for a total of 2720B
38% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=100} 3703.12 ns; σ=9.85 ns @ 3 trials, allocated 1 instances for a total of 16B
39% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=100} 4598.91 ns; σ=18.33 ns @ 3 trials, allocated 308 instances for a total of 10144B
40% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=100} 3709.97 ns; σ=12.28 ns @ 3 trials, allocated 1 instances for a total of 16B
41% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=100} 4520.00 ns; σ=27.93 ns @ 3 trials, allocated 308 instances for a total of 10144B
43% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=100} 3665.28 ns; σ=13.51 ns @ 3 trials, allocated 1 instances for a total of 16B
44% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=100} 4527.80 ns; σ=35.77 ns @ 3 trials, allocated 308 instances for a total of 10144B
45% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=100} 3701.99 ns; σ=22.06 ns @ 3 trials, allocated 1 instances for a total of 16B
46% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=100} 4498.57 ns; σ=45.15 ns @ 3 trials, allocated 308 instances for a total of 10144B
48% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=100} 3729.27 ns; σ=16.84 ns @ 3 trials, allocated 1 instances for a total of 16B
49% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=100} 4579.87 ns; σ=8.15 ns @ 3 trials, allocated 308 instances for a total of 10144B
50% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=1000} 254954.05 ns; σ=648.33 ns @ 3 trials, allocated 1 instances for a total of 16B
51% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=1000} 29495.00 ns; σ=202.71 ns @ 3 trials, allocated 374 instances for a total of 6160B
53% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=1000} 272123.84 ns; σ=1947.52 ns @ 3 trials, allocated 1 instances for a total of 16B
54% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=1000} 26549.46 ns; σ=169.74 ns @ 3 trials, allocated 374 instances for a total of 6160B
55% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=1000} 258246.52 ns; σ=1838.14 ns @ 3 trials, allocated 1 instances for a total of 16B
56% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=1000} 25816.29 ns; σ=238.66 ns @ 3 trials, allocated 374 instances for a total of 6160B
57% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=1000} 340760.25 ns; σ=714.81 ns @ 3 trials, allocated 1 instances for a total of 16B
59% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=1000} 26070.26 ns; σ=186.94 ns @ 3 trials, allocated 374 instances for a total of 6160B
60% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=1000} 255782.03 ns; σ=388.87 ns @ 3 trials, allocated 1 instances for a total of 16B
61% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=1000} 26950.40 ns; σ=491.82 ns @ 10 trials, allocated 1374 instances for a total of 30160B
63% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=1000} 268871.49 ns; σ=2890.36 ns @ 10 trials, allocated 1 instances for a total of 16B
64% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=1000} 50888.14 ns; σ=106.59 ns @ 3 trials, allocated 3011 instances for a total of 96528B
65% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=1000} 268566.99 ns; σ=2398.41 ns @ 4 trials, allocated 1 instances for a total of 16B
66% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=1000} 63228.83 ns; σ=495.26 ns @ 3 trials, allocated 3011 instances for a total of 96528B
68% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=1000} 265538.89 ns; σ=323.95 ns @ 3 trials, allocated 1 instances for a total of 16B
69% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=1000} 51922.10 ns; σ=491.28 ns @ 3 trials, allocated 3011 instances for a total of 96528B
70% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=1000} 267048.78 ns; σ=1934.21 ns @ 3 trials, allocated 1 instances for a total of 16B
71% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=1000} 54193.80 ns; σ=526.83 ns @ 3 trials, allocated 3011 instances for a total of 96528B
73% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=1000} 270239.69 ns; σ=1291.59 ns @ 3 trials, allocated 1 instances for a total of 16B
74% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=1000} 51265.07 ns; σ=547.18 ns @ 10 trials, allocated 3011 instances for a total of 96528B
75% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=SAWTOOTH, length=10000} 23672536.59 ns; σ=131459.47 ns @ 3 trials, allocated 1 instances for a total of 16B
76% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=SAWTOOTH, length=10000} 297356.00 ns; σ=1073.95 ns @ 3 trials, allocated 9374 instances for a total of 150160B
78% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=SAWTOOTH, length=10000} 42248173.91 ns; σ=364119.70 ns @ 3 trials, allocated 1 instances for a total of 16B
79% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=SAWTOOTH, length=10000} 273661.54 ns; σ=1544.97 ns @ 3 trials, allocated 9374 instances for a total of 150160B
80% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=SAWTOOTH, length=10000} 24378375.00 ns; σ=184303.85 ns @ 3 trials, allocated 1 instances for a total of 16B
81% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=SAWTOOTH, length=10000} 269039.83 ns; σ=123.09 ns @ 3 trials, allocated 9374 instances for a total of 150160B
83% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=SAWTOOTH, length=10000} 33378571.43 ns; σ=154321.88 ns @ 3 trials, allocated 1 instances for a total of 16B
84% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=SAWTOOTH, length=10000} 266848.28 ns; σ=1354.38 ns @ 3 trials, allocated 9374 instances for a total of 150160B
85% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=SAWTOOTH, length=10000} 24348450.00 ns; σ=158682.88 ns @ 3 trials, allocated 1 instances for a total of 16B
86% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=SAWTOOTH, length=10000} 281623.08 ns; σ=257.89 ns @ 3 trials, allocated 19374 instances for a total of 390160B
88% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=1, distribution=RANDOM, length=10000} 24604800.00 ns; σ=84624.92 ns @ 3 trials, allocated 1 instances for a total of 16B
89% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=1, distribution=RANDOM, length=10000} 826805.04 ns; σ=8011.71 ns @ 7 trials, allocated 30014 instances for a total of 931264B
90% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=6, distribution=RANDOM, length=10000} 24467945.29 ns; σ=230301.47 ns @ 4 trials, allocated 1 instances for a total of 16B
91% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=6, distribution=RANDOM, length=10000} 822419.69 ns; σ=8032.73 ns @ 9 trials, allocated 30014 instances for a total of 931264B
93% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=25, distribution=RANDOM, length=10000} 24666650.00 ns; σ=65345.42 ns @ 3 trials, allocated 1 instances for a total of 16B
94% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=25, distribution=RANDOM, length=10000} 819003.80 ns; σ=7662.68 ns @ 3 trials, allocated 30014 instances for a total of 931264B
95% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=7, distribution=RANDOM, length=10000} 24432650.00 ns; σ=210910.19 ns @ 3 trials, allocated 1 instances for a total of 16B
96% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=7, distribution=RANDOM, length=10000} 835849.98 ns; σ=9613.89 ns @ 10 trials, allocated 30014 instances for a total of 931264B
98% Scenario{vm=java, trial=0, benchmark=PairCounts_V1, K=111111111, distribution=RANDOM, length=10000} 24464100.00 ns; σ=41413.99 ns @ 3 trials, allocated 1 instances for a total of 16B
99% Scenario{vm=java, trial=0, benchmark=PairCounts_V2, K=111111111, distribution=RANDOM, length=10000} 835717.46 ns; σ=24729.21 ns @ 10 trials, allocated 30013 instances for a total of 931264B

 benchmark length distribution         K instances        B       ns linear runtime
PairCounts_V1     10     SAWTOOTH         1     1.000     16.0      119 =
PairCounts_V1     10     SAWTOOTH         6     1.000     16.0      116 =
PairCounts_V1     10     SAWTOOTH        25     1.000     16.0      125 =
PairCounts_V1     10     SAWTOOTH         7     1.000     16.0      116 =
PairCounts_V1     10     SAWTOOTH 111111111     1.000     16.0      125 =
PairCounts_V1     10       RANDOM         1     1.000     16.0      122 =
PairCounts_V1     10       RANDOM         6     1.000     16.0      121 =
PairCounts_V1     10       RANDOM        25     1.000     16.0      122 =
PairCounts_V1     10       RANDOM         7     1.000     16.0      121 =
PairCounts_V1     10       RANDOM 111111111     1.000     16.0      122 =
PairCounts_V1    100     SAWTOOTH         1     1.000     16.0     3531 =
PairCounts_V1    100     SAWTOOTH         6     1.000     16.0     3677 =
PairCounts_V1    100     SAWTOOTH        25     1.000     16.0     3253 =
PairCounts_V1    100     SAWTOOTH         7     1.000     16.0     3869 =
PairCounts_V1    100     SAWTOOTH 111111111     1.000     16.0     3240 =
PairCounts_V1    100       RANDOM         1     1.000     16.0     3703 =
PairCounts_V1    100       RANDOM         6     1.000     16.0     3710 =
PairCounts_V1    100       RANDOM        25     1.000     16.0     3665 =
PairCounts_V1    100       RANDOM         7     1.000     16.0     3702 =
PairCounts_V1    100       RANDOM 111111111     1.000     16.0     3729 =
PairCounts_V1   1000     SAWTOOTH         1     1.000     16.0   254954 =
PairCounts_V1   1000     SAWTOOTH         6     1.000     16.0   272124 =
PairCounts_V1   1000     SAWTOOTH        25     1.000     16.0   258247 =
PairCounts_V1   1000     SAWTOOTH         7     1.000     16.0   340760 =
PairCounts_V1   1000     SAWTOOTH 111111111     1.000     16.0   255782 =
PairCounts_V1   1000       RANDOM         1     1.000     16.0   268871 =
PairCounts_V1   1000       RANDOM         6     1.000     16.0   268567 =
PairCounts_V1   1000       RANDOM        25     1.000     16.0   265539 =
PairCounts_V1   1000       RANDOM         7     1.000     16.0   267049 =
PairCounts_V1   1000       RANDOM 111111111     1.000     16.0   270240 =
PairCounts_V1  10000     SAWTOOTH         1     1.000     16.0 23672537 ================
PairCounts_V1  10000     SAWTOOTH         6     1.000     16.0 42248174 ==============================
PairCounts_V1  10000     SAWTOOTH        25     1.000     16.0 24378375 =================
PairCounts_V1  10000     SAWTOOTH         7     1.000     16.0 33378571 =======================
PairCounts_V1  10000     SAWTOOTH 111111111     1.000     16.0 24348450 =================
PairCounts_V1  10000       RANDOM         1     1.000     16.0 24604800 =================
PairCounts_V1  10000       RANDOM         6     1.000     16.0 24467945 =================
PairCounts_V1  10000       RANDOM        25     1.000     16.0 24666650 =================
PairCounts_V1  10000       RANDOM         7     1.000     16.0 24432650 =================
PairCounts_V1  10000       RANDOM 111111111     1.000     16.0 24464100 =================
PairCounts_V2     10     SAWTOOTH         1     9.000    320.0      469 =
PairCounts_V2     10     SAWTOOTH         6     9.000    320.0      426 =
PairCounts_V2     10     SAWTOOTH        25     9.000    320.0      407 =
PairCounts_V2     10     SAWTOOTH         7     9.000    320.0      425 =
PairCounts_V2     10     SAWTOOTH 111111111    19.000    560.0      439 =
PairCounts_V2     10       RANDOM         1    34.000    960.0      482 =
PairCounts_V2     10       RANDOM         6    34.000    960.0      456 =
PairCounts_V2     10       RANDOM        25    34.000    960.0      464 =
PairCounts_V2     10       RANDOM         7    34.000    960.0      454 =
PairCounts_V2     10       RANDOM 111111111    34.000    960.0      482 =
PairCounts_V2    100     SAWTOOTH         1     9.000    320.0     3096 =
PairCounts_V2    100     SAWTOOTH         6     9.000    320.0     2872 =
PairCounts_V2    100     SAWTOOTH        25     9.000    320.0     2831 =
PairCounts_V2    100     SAWTOOTH         7     9.000    320.0     2748 =
PairCounts_V2    100     SAWTOOTH 111111111   109.000   2720.0     2942 =
PairCounts_V2    100       RANDOM         1   308.000  10144.0     4599 =
PairCounts_V2    100       RANDOM         6   308.000  10144.0     4520 =
PairCounts_V2    100       RANDOM        25   308.000  10144.0     4528 =
PairCounts_V2    100       RANDOM         7   308.000  10144.0     4499 =
PairCounts_V2    100       RANDOM 111111111   308.000  10144.0     4580 =
PairCounts_V2   1000     SAWTOOTH         1   374.000   6160.0    29495 =
PairCounts_V2   1000     SAWTOOTH         6   374.000   6160.0    26549 =
PairCounts_V2   1000     SAWTOOTH        25   374.000   6160.0    25816 =
PairCounts_V2   1000     SAWTOOTH         7   374.000   6160.0    26070 =
PairCounts_V2   1000     SAWTOOTH 111111111  1374.000  30160.0    26950 =
PairCounts_V2   1000       RANDOM         1  3011.000  96528.0    50888 =
PairCounts_V2   1000       RANDOM         6  3011.000  96528.0    63229 =
PairCounts_V2   1000       RANDOM        25  3011.000  96528.0    51922 =
PairCounts_V2   1000       RANDOM         7  3011.000  96528.0    54194 =
PairCounts_V2   1000       RANDOM 111111111  3011.000  96528.0    51265 =
PairCounts_V2  10000     SAWTOOTH         1  9374.000 150160.0   297356 =
PairCounts_V2  10000     SAWTOOTH         6  9374.000 150160.0   273662 =
PairCounts_V2  10000     SAWTOOTH        25  9374.000 150160.0   269040 =
PairCounts_V2  10000     SAWTOOTH         7  9374.000 150160.0   266848 =
PairCounts_V2  10000     SAWTOOTH 111111111 19374.000 390160.0   281623 =
PairCounts_V2  10000       RANDOM         1 30014.000 931264.0   826805 =
PairCounts_V2  10000       RANDOM         6 30014.000 931264.0   822420 =
PairCounts_V2  10000       RANDOM        25 30014.000 931264.0   819004 =
PairCounts_V2  10000       RANDOM         7 30014.000 931264.0   835850 =
PairCounts_V2  10000       RANDOM 111111111 30013.000 931264.0   835717 =

vm: java
trial: 0

Process finished with exit code 0</pre><p>C&#8217;est effectivement une information utile, la première version de l&#8217;algo, ne fait en fait qu&#8217;une seule allocation de 16B (donc en fait un seul objet), c&#8217;est à dire peanuts, on est dans du O(1) en complexité spatiale. La deuxième qui est notamment basée sur une HashMap alloue nettement plus d&#8217;objets, mais est définitivement plus rapide, on a on ici une complexité spatiale de O(n).</p>
<p>Comme quoi il y a potentiellement des compromis à faire dans le choix d&#8217;un algo, la rapidité ou la faible consommation mémoire peuvent venir avec un coût dans une autre dimension.</p>
<h1>Pour conclure</h1>
<ul>
<li>Premier point, il faut absolument être au point pour des tests d&#8217;embauche plus sur le sujet, même si je trouve limité ces tests dans leur capacité à identifier ou filtrer les bons développeurs (l&#8217;algorithmie n&#8217;est pas certainement pas le seul critère d&#8217;un individu doué), c&#8217;est toujours bien de pouvoir les reéussir !</li>
<li>Caliper offre un outillage plutôt facile d&#8217;utilisation pour faire des microbenchmark, dans la limite de validité d&#8217;un microbenchmark, il y a plein de mise en garde sur le sujet, sur le site de Caliper [<a href="http://code.google.com/p/caliper/wiki/JavaMicrobenchmarks">1</a>][<a href="http://code.google.com/p/caliper/wiki/JavaMicrobenchmarkReviewCriteria">2</a>], Cliff Click en a parlé aussi à JavaOne [<a href="http://www.azulsystems.com/events/javaone_2002/microbenchmarks.pdf">3</a>][<a href="http://www.azulsystems.com/events/javaone_2009/session/2009_J1_Benchmark.pdf">4</a>].</li>
<li>Quand on écrit du code c&#8217;est une bonne idée de penser à la complexité temporelle et spatiale, dont la notation pour les deux est le grand O. Caliper pourrait d&#8217;ailleurs se voir ajouter le moyen de mesurer la consommation mémoire (en lien avec la complexité spatiale). Évidement ce que je dis ne veut pas dire optimiser prématurément, mais juste de réfléchir à quel type de performance on peut s&#8217;attendre pour telle ou telle partie du code, et éventuellement de porter plus tard un effort spécifique.</li>
</ul>
<p>A noter que Caliper offre d&#8217;autres possibilités de mesurer la performance à travers une méthode annotée par <code>@ArbitraryMeasurement</code>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2012/08/29/caliper-ou-pourquoi-les-microbenchmarks-aident/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Script d&#8217;installation du JDK 5 sur MacOSX Lion et Mountain Lion (Mis à jour)</title>
		<link>https://blog.arkey.fr/2012/07/30/script-pour-installer-le-jdk-5-sur-macosx-lion/</link>
		<comments>https://blog.arkey.fr/2012/07/30/script-pour-installer-le-jdk-5-sur-macosx-lion/#comments</comments>
		<pubDate>Sun, 29 Jul 2012 22:17:40 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[j2se 5.0]]></category>
		<category><![CDATA[java5]]></category>
		<category><![CDATA[jdk5]]></category>
		<category><![CDATA[lion]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[mountain lion]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=274</guid>
		<description><![CDATA[MAJ 29/07/2012: Le script a été mis à jour pour fonctionner avec Mac OS X Mountain Lion. Le script a été mis à jour pour télécharger lui même le DMG chez Apple, en bref il n&#8217;y a plus qu&#8217;à commencer à l&#8217;étape 2. Original 22/08/2011 : Avec l&#8217;arrivée de Lion, Apple change les choses avec [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><strong>MAJ 29/07/2012</strong>: Le script a été mis à jour pour fonctionner avec Mac OS X Mountain Lion. Le script a été mis à jour pour télécharger lui même le DMG chez Apple, en bref il n&#8217;y a plus qu&#8217;à commencer à l&#8217;étape 2.</p>
<p><a href="http://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_install_mountain_lion.png"><img class=" wp-image-357    alignnone img-thumbnail img-responsive" title="jdk5_install_mountain_lion" src="http://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_install_mountain_lion.png" alt="JDK 5 installation on Mountain Lion" width="542" height="355" srcset="https://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_install_mountain_lion.png 955w, https://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_install_mountain_lion-300x196.png 300w" sizes="(max-width: 542px) 100vw, 542px" /></a></p>
<hr />
<p><strong>Original 22/08/2011</strong> : Avec l&#8217;arrivée de Lion, Apple change les choses avec Java. Heureusement s&#8217;il s&#8217;agit d&#8217;une mise à jour depuis Snow Leopard, vous ne perdrez pas votre runtime JDK 6, en revanche si vous faites une installation clean, et bien il faudra télécharger le runtime ici :</p>
<blockquote><p><a title="Java 6 Runtime pour Lion" href="http://support.apple.com/kb/DL1421">http://support.apple.com/kb/DL1421</a></p></blockquote>
<p>Bon ça fait une chose de plus pour nous ennuyer, mais bon comme toujours pour ceux qui veulent bosser sur un JDK 1.5, il vous faudra tricher un peu plus, il n&#8217;y a pas de mise à jour standard ou facile pour installer le JDK 5 sur 10.7.</p>
<p>Certains ont trouvé l&#8217;astuce en téléchargeant la mise à jour Java pour Mac OS X 10.5, et avec quelques outils et commandes dans le terminal. Cela dit le processus est un poil long. Du coup je me suis codé un petit script pour automatiser ces étapes. Pour l&#8217;instant le script repose sur un téléchargement manuel de cette mise à jour.</p>
<ol>
<li>En premier on télécharge la mise à jour du JDK5 ici :<br />
<blockquote><p><a title="Mise à jour Java pour Leopard" href="http://support.apple.com/kb/DL1359">http://support.apple.com/kb/DL1359</a></p></blockquote>
</li>
<li>Ensuite dans le même répertoire on y téléchargera le <strong><a title="Script d'install du JDK 5 sur Lion" href="https://gist.github.com/raw/1163008/146a0e1378f3daf8ab7d5e981530764e64ca770b/install_jdk5_lion.sh">script</a></strong></li>
<li>Dans un terminal dans le dossier du téléchargement<br />
[plain]chmod +x install_jdk5_lion.sh[/plain]</li>
<li>Il faut être <strong>root</strong>, attention quand même, le script fonctionne sur les environnements Lion que j&#8217;ai pu testé, mais il peut très bien casser votre système, déclencher un tempête ou je ne sais quoi encore&#8230; je ne garantis rien.<br />
[plain]sudo -s[/plain]</li>
<li>Bref il se lance comme ça :<br />
[plain]./install_jdk5_lion.sh[/plain]</li>
<li>Si tout se passe bien alors, les préférences Java de Mac s&#8217;ouvriront en listant le JDK 5.</li>
<li>exit</li>
</ol>
<p>En images, ça donne :</p>
<p><a href="http://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_lion_install_terminal.png"><img class="alignnone size-full wp-image-279 img-thumbnail img-responsive" title="jdk5_lion_install_terminal" src="http://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_lion_install_terminal.png" alt="" width="593" height="399" srcset="https://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_lion_install_terminal.png 972w, https://blog.arkey.fr/wp-content/uploads/2011/08/jdk5_lion_install_terminal-300x201.png 300w" sizes="(max-width: 593px) 100vw, 593px" /></a></p>
<p><a href="http://blog.arkey.fr/wp-content/uploads/2011/08/lion_java_preferences.png"><img class="alignnone size-full wp-image-280 img-thumbnail img-responsive" title="lion_java_preferences" src="http://blog.arkey.fr/wp-content/uploads/2011/08/lion_java_preferences.png" alt="" width="577" height="402" srcset="https://blog.arkey.fr/wp-content/uploads/2011/08/lion_java_preferences.png 721w, https://blog.arkey.fr/wp-content/uploads/2011/08/lion_java_preferences-300x208.png 300w" sizes="(max-width: 577px) 100vw, 577px" /></a></p>
<p>Evidement si vous repérez une coquille, je suis à l&#8217;écoute. Bonne soirée <img src="https://s.w.org/images/core/emoji/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><strong>EDIT 29/08/2011</strong>: Tant qu&#8217;à faire autant montrer comment avoir plusieurs JDK dans IntelliJ sous macosx.</p>
<ol>
<li>Donc une fois le projet ouvert, il faut aller dans les préférences du projet (Project Settings).<br />
<a href="http://blog.arkey.fr/wp-content/uploads/2011/08/project_setting-e1314642274278.png"><img class="alignnone size-full wp-image-289 img-thumbnail img-responsive" title="project_setting" src="http://blog.arkey.fr/wp-content/uploads/2011/08/project_setting-e1314642274278.png" alt="IntelliJ Project Setting" width="496" height="327" srcset="https://blog.arkey.fr/wp-content/uploads/2011/08/project_setting-e1314642274278.png 1033w, https://blog.arkey.fr/wp-content/uploads/2011/08/project_setting-e1314642274278-300x197.png 300w, https://blog.arkey.fr/wp-content/uploads/2011/08/project_setting-e1314642274278-1024x675.png 1024w" sizes="(max-width: 496px) 100vw, 496px" /></a></li>
<li>Ensuite ajouter le JSDK.<br />
<a href="http://blog.arkey.fr/wp-content/uploads/2011/08/add_new_jsdk.png"><img class="alignnone size-full wp-image-290 img-thumbnail img-responsive" title="add_new_jsdk" src="http://blog.arkey.fr/wp-content/uploads/2011/08/add_new_jsdk.png" alt="Add New JSDK" width="190" height="211" /></a></li>
<li>Puis sélectionner dans l&#8217;explorateur le dossier /System/Library/Java/JavaVirtualMachines/1.5.0/Contents/Home<br />
<a href="http://blog.arkey.fr/wp-content/uploads/2011/08/choose_jdk5_home.png"><img class="alignnone size-full wp-image-291 img-thumbnail img-responsive" style="border-style: initial; border-color: initial;" title="choose_jdk5_home" src="http://blog.arkey.fr/wp-content/uploads/2011/08/choose_jdk5_home-e1314642723756.png" alt="Choose JDK 5 Home" width="496" height="236" /></a></li>
<li>Hop, c&#8217;est fini, dans IntelliJ vous avez le JDK 5<br />
<a href="http://blog.arkey.fr/wp-content/uploads/2011/08/intellij_found_it.png"><img class="alignnone size-full wp-image-292 img-thumbnail img-responsive" title="intellij_found_it" src="http://blog.arkey.fr/wp-content/uploads/2011/08/intellij_found_it-e1314642860664.png" alt="" width="496" height="325" /></a></li>
</ol>
<p>Idée originale : <a href="http://www.s-seven.net/zend_5x_lion">Zend Studio <em>5</em>.x for OS X <em>Lion</em> (<em>Java</em> SE 6)</a></p>
<p>Sources :<br />
<script type="text/javascript" src="https://gist.github.com/1163008.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2012/07/30/script-pour-installer-le-jdk-5-sur-macosx-lion/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Hackergarten Paris &#8211; ce qu&#8217;il faut savoir sur les projets</title>
		<link>https://blog.arkey.fr/2012/03/05/hackergarten-paris-ce-quil-faut-savoir-sur-les-projets/</link>
		<comments>https://blog.arkey.fr/2012/03/05/hackergarten-paris-ce-quil-faut-savoir-sur-les-projets/#comments</comments>
		<pubDate>Sun, 04 Mar 2012 23:54:28 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[infinitest]]></category>
		<category><![CDATA[jenkins]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=337</guid>
		<description><![CDATA[Hello à tous, Mercredi 7 mars (à 19h) aura lieu la 2ème session Hackergarten. Après Soat, on a le plaisir d&#8217;être hébergé par Valtech (103 Rue de Grenelle, 75007 Paris) et il y aura des pizzas, gros merci à eux. Hackergarten c&#8217;est le rendez-vous des gens qui veulent participer aux projets opensource. L&#8217;idée c&#8217;est, dans un format de [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Hello à tous,</p>
<p><img class="alignnone img-thumbnail img-responsive" style="vertical-align: baseline; border-image: initial; border-width: 1px; border-color: black; border-style: solid; background-color: slategray;" title="Hackergarten Logo BW" src="http://hackergarten.net/hackergarten_b_and_w_small.png" alt="Hackergarten Logo" width="392" height="150" /></p>
<p><strong>Mercredi 7 mars</strong> (à 19h) aura lieu la 2ème session Hackergarten. Après <strong>Soat</strong>, on a le plaisir d&#8217;être hébergé par <strong>Valtech</strong> (103 Rue de Grenelle, 75007 Paris) et il y aura des <strong>pizzas</strong>, gros merci à eux.</p>
<blockquote title="Hackergarten Paris"><p>Hackergarten c&#8217;est le rendez-vous des gens qui veulent participer aux projets opensource. L&#8217;idée c&#8217;est, dans un format de 3h, de <strong>contribuer</strong> un <strong>logiciel</strong>, un <strong>fix</strong>, un <strong>feature</strong>, une <strong>documentation</strong> dont d&#8217;autres pourraient avoir l&#8217;usage. Il s&#8217;articule autour de commiters actifs pour mentorer les hackers qui participent à l&#8217;évènement.</p></blockquote>
<p>Bref que du bon. Pour la planification de l&#8217;évènement c&#8217;est par là ⇒ <a href="http://hackergarten-paris.eventbrite.com/">http://hackergarten-paris.eventbrite.com/</a></p>
<p>Alors pour éviter les soucis de setup le jour J, ce post donne quelques informations sur ce qu&#8217;il y aurait à récupérer ou faire en avance sur votre machine. Si vous avez des questions ou si vous voulez participez aux discussions : inscrivez vous sur la mailing-list à cette adresse ⇒ <a href="http://groups.google.com/group/hackergarten-paris/">http://groups.google.com/group/hackergarten-paris/</a></p>
<p><span id="more-337"></span></p>
<h2>Hibernate OGM / Hibernate Search ⇐ mentoré par Emmanuel Bernard</h2>
<p><span style="text-decoration: underline;">IDE :</span> <strong>IntelliJ</strong> mais <strong>Eclipse</strong> fait l&#8217;affaire</p>
<p><span style="text-decoration: underline;">Pour builder :</span> <strong>Maven 3.0.3</strong><br />
JDK 1.6 recommandé<br />
changer les <strong>~/.m2/settings.xml</strong> selon <a href="https://community.jboss.org/wiki/MavenGettingStarted-Users" target="_blank">https://community.jboss.org/<wbr>wiki/MavenGettingStarted-Users</wbr></a></p>
<p><strong>Installer Cassandra 1.0.8 (download sur Apache)</strong><br />
Et pour les motivés NoSQL, installer votre moteur préféré aussi histoire de contribuer un dialect pour Hibernate OGM</p>
<p>Forker + cloner localement<br />
&#8211; git clone <a href="https://github.com/hibernate/hibernate-search" target="_blank">https://github.com/hibernate/<wbr>hibernate-search</wbr></a><br />
&#8211; git clone <a href="https://github.com/hibernate/hibernate-ogm" target="_blank">https://github.com/hibernate/<wbr>hibernate-ogm</wbr></a></p>
<p>Cloner<br />
&#8211; git clone <a href="https://code.google.com/a/apache-extras.org/p/cassandra-jdbc/" target="_blank">https://code.google.com/a/<wbr>apache-extras.org/p/cassandra-</wbr><wbr>jdbc/</wbr></a></p>
<p>Lancer <strong>mvn clean install</strong> sous chacun des clones pour être sûr que Maven télécharge bien la terre.</p>
<h2>Maven / Jenkins ⇐ mentoré par Arnaud Héritier</h2>
<p><span style="text-decoration: underline;">IDE :</span> Pour Maven &amp; Jenkins : IntelliJ ou eclipse + m2e versions recentes si possibles</p>
<p><strong>Git</strong> pour <strong>Jenkins</strong>, <strong>SVN</strong> pour <strong>Maven</strong></p>
<p><span style="text-decoration: underline;">Pour builder :</span>  <strong>Maven</strong> 2.2.1 min, 3.0.x serait un mieux<br />
(De memoire pas de settings additionnels pour seulement builder)</p>
<div><span style="text-decoration: underline;">Jenkins :</span></div>
<div>EDIT : Il faut modifier son <strong>settings.xml</strong>, voir : <a href="https://wiki.jenkins-ci.org/display/JENKINS/Plugin+tutorial">https://wiki.jenkins-ci.org/display/JENKINS/Plugin+tutorial</a></div>
<div>Arnaud me dit à l&#8217;oreille que suite à des changements chez Oracle il faut ajouter ce miroir dans le settings.xml</div>
<div>
<pre class="crayon-plain-tag">&lt;mirror&gt;
  &lt;id&gt;repo.jenkins-ci.org&lt;/id&gt;
  &lt;url&gt;http://repo.jenkins-ci.org/public/&lt;/url&gt;
  &lt;mirrorOf&gt;m.g.o-public&lt;/mirrorOf&gt;
&lt;/mirror&gt;</pre>
</div>
<div>Checkout du plugin qui vous interesse puis <strong>mvn clean install hpi:run</strong></div>
<div></div>
<div><span style="text-decoration: underline;">Maven :</span></div>
<div>Checkout du plugin qui vous interesse puis <strong>mvn clean install -Prun-its</strong></div>
<h2>Infinitest ⇐ mentoré par David Gageot</h2>
<div><span style="text-decoration: underline;">IDE :</span> <strong>Eclipse</strong> mais <strong>IntelliJ</strong> fait l&#8217;affaire</div>
<div>Utiliser <strong>mvn eclipse:eclipse</strong> plutot que <strong>m2eclipse</strong></div>
<div>
<div></div>
<div><span style="text-decoration: underline;">Pour builder :</span> Maven 3.0.3</div>
<div>JDK 1.6 recommandé</div>
<div></div>
</div>
<div>Forker + cloner localement <a href="https://github.com/infinitest/infinitest" target="_blank">https://github.com/<wbr>infinitest/infinitest</wbr></a></div>
<p>Lancer <strong>mvn dependency:go-offline</strong> pour récupérer toutes les dépendances</p>
<h2>Mockito ⇐ mentoré par Brice Dutheil</h2>
<p><span style="text-decoration: underline;">IDE :</span> <strong>IntelliJ</strong> en particulier, la <strong>version Community</strong> suffira. Eclipse peut faire l&#8217;affaire. Attention on a eu des soucis avec Netbeans la dernière fois.</p>
<p><span style="text-decoration: underline;">Pour Builder :</span> <strong>Ant</strong> (IntelliJ contient un Ant)<br />
JDK 5 préféré, mais pas obligatoire.</p>
<p>Forker et cloner localement depuis Google code : <a href="http://code.google.com/p/mockito/source/checkout">http://code.google.com/p/mockito/source/checkout</a><br />
Attention ici c&#8217;est du <strong>mercurial</strong>.</p>
<p>Il n&#8217;y a plus qu&#8217;à ouvrir les fichiers du projet.</p>
<h2>FluentLenium ⇐ mentoré par Mathilde Lemée</h2>
<p><span style="text-decoration: underline;">IDE :</span> Un IDE qui gère maven, genre IntelliJ.</p>
<p><span style="text-decoration: underline;">Pour Builder :</span> Maven</p>
<p>Checkout depuis : <a href="https://github.com/FluentLenium/FluentLenium">https://github.com/FluentLenium/FluentLenium</a></p>
<h2>Votre projet</h2>
<p>Et oui si vous avez une idée à coder en Open Source et que vous cherchez des intéressés c&#8217;est peut-être l&#8217;endroit pour en parler et dresser un plan <img src="https://s.w.org/images/core/emoji/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>1000 mercis</h2>
<p>Gros merci à tous ceux qui participent aux Hackergarten Paris</p>
<ul>
<li>Arnaud Héritier</li>
<li>Guillaume Laforge</li>
<li>Emmanuel Bernard</li>
<li>David Gageot</li>
<li>Eric Lefevre</li>
<li>Mathilde Lemée</li>
<li>Et vous tous qui venez</li>
</ul>
<p>Gros merci aussi à ceux qui hébergent l&#8217;évènement, c&#8217;est bien sympa :</p>
<ul>
<li>Soat</li>
<li>Valtech</li>
</ul>
<p>Évidement merci à <strong>Hamlet D&#8217;Harcy</strong> pour avoir initier l&#8217;idée là bas en Suisse <img src="https://s.w.org/images/core/emoji/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2012/03/05/hackergarten-paris-ce-quil-faut-savoir-sur-les-projets/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Mockito 1.9.0 is out &#8211; Bientôt sur les repos maven</title>
		<link>https://blog.arkey.fr/2011/12/19/quoi-de-neuf-docteur-dans-mockito-1-9/</link>
		<comments>https://blog.arkey.fr/2011/12/19/quoi-de-neuf-docteur-dans-mockito-1-9/#respond</comments>
		<pubDate>Mon, 19 Dec 2011 08:37:06 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[constructor injection]]></category>
		<category><![CDATA[mockito]]></category>

		<guid isPermaLink="false">http://dutheil.brice.online.fr/blog/?p=243</guid>
		<description><![CDATA[EDIT: Hop. Enfin la release 1.9.0 est dispo en téléchargement. Après pas mal de travail avec des périodes plus ou moins intenses &#8211; bref les vicissitudes du développement Open Source &#8211; le projet sort une nouvelle version 1.9.0 en Release Candidate, avec des bugfixes et bien sûr des nouvelles features. Il y a un changelog [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: normal;"><strong>EDIT:</strong> Hop. Enfin la release 1.9.0 est dispo en téléchargement.</span></p>
<p><span style="font-weight: normal;">Après pas mal de travail avec des périodes plus ou moins intenses &#8211; <em>bref les vicissitudes du développement Open Source</em> &#8211; le projet sort une nouvelle version <strong>1.9.0</strong> en <del>Release Candidate</del>, avec des bugfixes et bien sûr des nouvelles features. Il y a un <a title="Release notes de Mockito 1.9.0" href="http://code.google.com/p/mockito/wiki/ReleaseNotes">changelog</a> mais dans les faits le billet suivant liste brièvement ce qui est nouveau. Ah oui la version est téléchargeable <a title="Télécharger la version 1.9.0 de Mockito" href="http://code.google.com/p/mockito/downloads/detail?name=mockito-1.9.0.zip">ici</a> et bientôt disponible sur le central maven.</span></p>
<ul>
<li>Pour être plus fluent et expressif, l&#8217;API introduit les alias <code>then</code> et <code>will</code> pour les réponses personnalisées (<code>Answer</code>). Ainsi que d&#8217;autres petits tweak de l&#8217;API:<br />
<pre class="crayon-plain-tag">@Test
public void engine_should_only_work_with_diesel() {
  given(engine.start()).will(throwExceptionIfEssenceInsteadOfDiesel());
  // ...
}

private Answer throwExceptionIfEssenceInsteadOfDiesel() {
  return new Answer&lt;EngineStatus&gt;() {
    public EngineStatus answer(InvocationOnMock invocation) {
      // answer code
    }
  };
}</pre>
</li>
<li>Les mocks peuvent maintenant être déclaré dans la configuration du stub, sur une ligne.<br />
<pre class="crayon-plain-tag">DieselEngine de = given(mock(DieselEngine.class).start()).willThrow(TankIsEmpty.class).getMock();</pre>
</li>
<li>On peut maintenant renvoyer la classe d&#8217;une exception plutôt que son instance.<br />
<pre class="crayon-plain-tag">given(someMock).willThrow(IllegalArgumentException.class, SomethingIsWrongException.class);</pre>
</li>
<li>Si jamais vous avez besoin de debugguer un bout de code ou les interactions sont non prédictibles, il est maintenant possible de loguer les invocations du mock ou de l&#8217;espion. Attention, bien qu&#8217;utile à l&#8217;occasion avec du code legacy, quand même si jamais ce besoin s&#8217;en fait sentir sur un nouveau développement c&#8217;est que ce code devient trop complexe.<br />
<pre class="crayon-plain-tag">List mockedList = mock(List.class, withSettings().verboseLogging());
mockedList.get(0);</pre><br />
On pourra également ajouter des callbacks sur chaque interaction du mock.<br />
<pre class="crayon-plain-tag">Observer observer = mock(Observer.class, withSettings().invocationListeners(listener1, listener2));
willThrow(IllegalArgumentException.class).given(observer.update(observable, "what has changed"));</pre>
</li>
<li>Pas mal de travail a été fait sur les annotations. Maintenant il n&#8217;est plus nécéssaire d&#8217;initialiser un champ annoté par <code>@Spy</code> s&#8217;il existe dans la classe un constructeur sans argument.<br />
<pre class="crayon-plain-tag">@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
  // pas besoin d'initialiser le champs
  @Spy private ArrayList spiedArrayList;

  @Test public void verify_some_interactions() {
    spiedArrayList.iterator();
    verify(spiedArrayList, once()).iterator();
  }
}</pre>
</li>
<li>Et pour la fin mais pas des moindres, le mécanisme d&#8217;injection de mockito supporte maintenant l&#8217;injection par constructeur. A l&#8217;heure actuelle, seul les mocks et spies déclaré dans le test en tant que champs pourront être injecté dans le constructeur du champs annoté par <code>@InjectMocks</code>.<br />
<pre class="crayon-plain-tag">@RunWith(MockitoJUnitRunner.class)
public class EngineTest {
  @Mock Diesel diesel;
  @InjectMocks Engine engine;

  @Test public void engine_should_consume_Diesel() {
    engine.start();
  }
}</pre><br />
Ou <code>Engine</code> a un constructeur avec le paramètre Diesel.<br />
<pre class="crayon-plain-tag">public class Engine {
  Diesel diesel;
  public Engine(Diesel diesel) {
    this.diesel = diesel;
  }

  public boolean start() {
    checkNotEmpty(diesel);
    // ...
  }
  // ...
}</pre>
</li>
</ul>
<p>Pour l&#8217;instant en RC, cette release permettra d&#8217;adoucir les angles si nous en avons loupé certains éléments. N&#8217;hésitez pas à nous poser des questions sur la <a title="Mockito mailing list" href="http://groups.google.com/group/mockito" target="_blank">mailing list</a> ou <a title="StackOverflow" href="http://stackoverflow.com/" target="_blank">stackoverflow</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2011/12/19/quoi-de-neuf-docteur-dans-mockito-1-9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quelques Live Template IntelliJ pour Mockito</title>
		<link>https://blog.arkey.fr/2011/10/21/quelques-live-template-intellij-pour-mockito/</link>
		<comments>https://blog.arkey.fr/2011/10/21/quelques-live-template-intellij-pour-mockito/#respond</comments>
		<pubDate>Fri, 21 Oct 2011 18:06:46 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[intellij]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[test unitaire]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=329</guid>
		<description><![CDATA[Hello, j&#8217;en avais un peu marre d&#8217;écrire régulièrement voire répétitivement dans mes tests les constructions mockito. Pour ça je me suis créé dans mon IDE favori, IntelliJ, ce qu&#8217;on appelle des Live Template. Ces templates permettent à partir d&#8217;une abréviation d&#8217;insérer des fragments de code. Ainsi par exemple : Taper iter dans votre éditeur puis [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Hello, j&#8217;en avais un peu marre d&#8217;écrire régulièrement voire répétitivement dans mes tests les constructions mockito.</p>
<p>Pour ça je me suis créé dans mon IDE favori, <a title="IntelliJ IDEA" href="http://www.jetbrains.com/idea/">IntelliJ</a>, ce qu&#8217;on appelle des Live Template. Ces templates permettent à partir d&#8217;une abréviation d&#8217;insérer des fragments de code. Ainsi par exemple :</p>
<p>Taper <code>iter</code> dans votre éditeur puis de faire <kbd>Ctrl+J</kbd> (sous OSX) va développer cette abréviation dans le bout de code ci-dessous (suivant le contexte bien entendu)</p>
<p></p><pre class="crayon-plain-tag">for (TypeInIterable type : someIterable) {

}</pre><p></p>
<p>Taper sur <kbd>Ctrl+J</kbd> (sous OSX) vous permet de lister les abréviations disponible dans le contexte courant.</p>
<h3>Les Live Template pour Mockito</h3>
<p>Bien qu&#8217;imparafaite pour des raisons de limite technique d&#8217;IntelliJ, elles sauvent un minimum de temps, multiplié par le nombre de test. Malheureusement il n&#8217;y a pas non plus d&#8217;import export uniquement pour les live template, il faut donc se taper la configuration de intellij à la main. Cela dit il est possible de contourner partiellement ce problème avec la sauvegarde de la configuration personnelle sur les serveurs intellij, ou encore d&#8217;exporter la configuration pour les live templates, les file templates, et encore autre chose.</p>
<p>J&#8217;ai défini toutes ces annotations dans un nouveau groupe &#8216;test&#8217;, et j&#8217;ai activé pour toutes le contexte Java, avec reformatage et simplification du nom qualifié.</p>
<ol>
<li><span style="text-decoration: underline;">Description :</span> Creates a field with the @Mock annotation<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;am&#8217;<br />
<span style="text-decoration: underline;">Template text :</span><br />
<pre class="crayon-plain-tag">@org.mockito.Mock private $TYPE$ $MOCK_FIELD$</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">TYPE</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK_FIELD</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">suggestVariableName()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span> Creates a field with the @Spy annotation<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;as&#8217;<br />
<span style="text-decoration: underline;">Template text :</span><br />
<pre class="crayon-plain-tag">@org.mockito.Spy private $TYPE$ $MOCK_FIELD$</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">TYPE</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK_FIELD</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">suggestVariableName()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span> Creates a field with the @InjectMocks annotation<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;aim&#8217;<br />
<span style="text-decoration: underline;">Template text :</span><br />
<pre class="crayon-plain-tag">@org.mockito.InjectMocks private $TYPE$ $MOCK_FIELD$</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">TYPE</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK_FIELD</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">suggestVariableName()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span> Add @RunWith(MockitoJUnitRunner.class)<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;rwm&#8217;<br />
<span style="text-decoration: underline;">Template text :</span><br />
<pre class="crayon-plain-tag">@org.junit.runner.RunWith(org.mockito.runners.MockitoJUnitRunner.class)</pre></li>
<li><span style="text-decoration: underline;">Description :</span> BDD Stub mock with given(&#8230;).willReturn(&#8230;) style<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;gw&#8217;<br />
<span style="text-decoration: underline;">Template text :</span><br />
<pre class="crayon-plain-tag">given($MOCK$).willReturn($ARGS$)$END$</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">ARGS</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span> BDD Stub spy/mock with willReturn(&#8230;).given(&#8230;) style<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;wg&#8217;<br />
<span style="text-decoration: underline;">Template text :</span><br />
<pre class="crayon-plain-tag">org.mockito.BDDMockito.willReturn($RETURNED$).given($MOCK$).$CALL$ $END$</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">RETURNED</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">complete()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">CALL</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">complete()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span> Inserts a verify(&#8230;) statement<span style="text-decoration: underline;"><br />
Abbréviation :</span>&#8216;verif&#8217;<span style="text-decoration: underline;"><br />
Template text :</span><pre class="crayon-plain-tag">org.mockito.Mockito.verify($MOCK$).$CALL$</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">CALL</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">complete()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span> Inserts Mockito.inOrder(mocks) followed by inOrder.verify(&#8230;) statement<br />
<span style="text-decoration: underline;">Abbréviation :</span> &#8216;ioverif&#8217;<span style="text-decoration: underline;"><br />
Template text :</span><pre class="crayon-plain-tag">org.mockito.InOrder $inOrderVar$ = org.mockito.Mockito.inOrder($MOCKS$);
$IN_ORDER_VAR$.verify($MOCK$).$CALL$;</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">IN_ORDER_VAR</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">suggestVariableName()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCKS</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"> MOCK</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"> CALL</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">complete()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
<li><span style="text-decoration: underline;">Description :</span>Inserts a verify(&#8230;) statement<span style="text-decoration: underline;"><br />
Abbréviation :</span>&#8216;verif&#8217;<span style="text-decoration: underline;"><br />
Template text :</span><pre class="crayon-plain-tag">$IN_ORDER_VAR$.verify($MOCK$).$CALL$;</pre></p>
<p><span style="text-decoration: underline;">Les variables du templates sont :</span></p>
<table  style="border-color: #000000; border-width: 1px; background-color: #ffffff; width: 100%;" border="0" class="table table-bordered table-striped">
<tbody>
<tr style="background-color: #ffefd5;">
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Name</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Expression</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Default value</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">Skip if defined</td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">IN_ORDER_VAR</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;org.mockito.InOrder&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">MOCK</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">variableOfType(&#8220;Object&#8221;)</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
<tr>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">CALL</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;">complete()</td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
<td style="border-color: #000000; width: 25%; border-style: solid; border-width: 1px;"></td>
</tr>
</tbody>
</table>
</li>
</ol>
<p>Voilà donc les templates que je me suis créé pour IntelliJ, il manque certainement des cas d&#8217;utilisation, mais je trouvais plus judicieux de mettre ces cas là au moins. Pour nos amis Eclipse oou Netbeans, il y a des fonctionnalités comparables plus ou moins évoluées (de mémoire le système d&#8217;Eclipse est plutôt pas mal).</p>
<h3>Références</h3>
<ul>
<li><a title="Live Templates" href="http://www.jetbrains.com/idea/webhelp/live-templates-2.html">Live Templates</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2011/10/21/quelques-live-template-intellij-pour-mockito/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Afficher les properties d&#8217;un projet maven</title>
		<link>https://blog.arkey.fr/2011/10/18/afficher-les-properties-dun-projet-maven/</link>
		<comments>https://blog.arkey.fr/2011/10/18/afficher-les-properties-dun-projet-maven/#respond</comments>
		<pubDate>Tue, 18 Oct 2011 10:15:28 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[maven]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[properties]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=318</guid>
		<description><![CDATA[Pas vraiment un article mais plutôt une astuce que j&#8217;ai utilisé pour afficher la valeur de certaines property. Il faut ajouter dans la section build/plugins du pom une tache ant qui fera simplement un echo. A noter que cette tache est disponible dans la phase validate. [crayon-57626d07bdfa5320350628/] Cela dit n&#8217;étant pas un expert maven, il [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pas vraiment un article mais plutôt une astuce que j&#8217;ai utilisé pour afficher la valeur de certaines property.</p>
<p>Il faut ajouter dans la section build/plugins du pom une tache ant qui fera simplement un echo. A noter que cette tache est disponible dans la phase validate.</p><pre class="crayon-plain-tag">&lt;build&gt;
&lt;plugins&gt;

    &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-antrun-plugin&lt;/artifactId&gt;
        &lt;version&gt;1.1&lt;/version&gt;
        &lt;executions&gt;
            &lt;execution&gt;
                &lt;phase&gt;validate-property&lt;/phase&gt;
                &lt;goals&gt;
                    &lt;goal&gt;run&lt;/goal&gt;
                &lt;/goals&gt;
                &lt;configuration&gt;
                    &lt;tasks&gt;
                        &lt;echo&gt;Displaying properties resolution&lt;/echo&gt;
                        &lt;echo&gt;some.property]= ${some.property}&lt;/echo&gt;
                        &lt;echo&gt;project.build.directory = ${project.build.directory&lt;/echo&gt;

                        &lt;echo&gt;project.build.finalName= ${project.build.finalName}&lt;/echo&gt;
                    &lt;/tasks&gt;
                &lt;/configuration&gt;
            &lt;/execution&gt;
        &lt;/executions&gt;
    &lt;/plugin&gt;

&lt;/plugins&gt;
&lt;build&gt;</pre><p>Cela dit n&#8217;étant pas un expert maven, il y existe peut-être une solution plus élégante, un commentaire est le bienvenu dans ce cas.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2011/10/18/afficher-les-properties-dun-projet-maven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tester votre code JMX dans des conditions pseudo réelle.</title>
		<link>https://blog.arkey.fr/2011/10/14/tester-votre-code-jmx-dans-des-conditions-pseudo-reelle/</link>
		<comments>https://blog.arkey.fr/2011/10/14/tester-votre-code-jmx-dans-des-conditions-pseudo-reelle/#respond</comments>
		<pubDate>Fri, 14 Oct 2011 11:01:31 +0000</pubDate>
		<dc:creator><![CDATA[Brice Dutheil]]></dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[jmx]]></category>
		<category><![CDATA[test unitaire]]></category>

		<guid isPermaLink="false">http://blog.arkey.fr/?p=303</guid>
		<description><![CDATA[Vous devez écrire du code qui fait appel à JMX, en bon citoyen et bon développeur vous voulez tester ce code. Première approche; vous enregistrez vos MBean sur un MBeanServer, disons celui de la plateforme (avec Java 6 : ManagementFactory.getPlatformMBeanServer()). [crayon-57626d07be87e369736251/] Étant donné que MBeanServer étends MBeanServerConnection il est possible d’exécuter des querys, de faire [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Vous devez écrire du code qui fait appel à JMX, en bon citoyen et bon développeur vous voulez tester ce code.</p>
<p>Première approche; vous enregistrez vos MBean sur un <code>MBeanServer</code>, disons celui de la plateforme (avec Java 6 : <code>ManagementFactory.getPlatformMBeanServer()</code>).</p><pre class="crayon-plain-tag">mBeanServer.registerMBean(theMBean, theMBean.getObjectName());</pre><p>Étant donné que <code>MBeanServer</code> étends <code>MBeanServerConnection</code> il est possible d’exécuter des querys, de faire des invocations sur les MBean etc. Si le code est suffisamment isolé des aspects techniques de connexion à JMX, vous passerez le <code>MBeanServer</code> en lieu et place de la <code>MBeanServerConnection</code>.</p>
<p>Supposons le code suivant.</p><pre class="crayon-plain-tag">public class OperateOnJMXConnection implements JMXOperation {

    public void perform(MBeanServerConnection connection) {
        // doing some stuff there
    }

    public Result getResult() { return result; }
}</pre><p>Pour tester ce code il faudrait alors écrire :</p><pre class="crayon-plain-tag">@Test
public void do_not_fail() {
    operateOnJMXConnection.perform(mbeanServer);

    assertThat(result).satisfies(someCondition);
}</pre><p>Mais voilà, vous restez en local, et par exemple si vous avez merdé sur la sérialisation de vos beans, vous ne verrez pas d&#8217;échec dans vos test et vous aurez une surprise en prod, ou avant si votre projet a un processus qualité décent.</p>
<p>Évidement il y a une solution, l&#8217;idée c&#8217;est de pouvoir se connecter au <code>mBeanServer</code> local à votre processus (typiquement dans maven 3, l’exécution de vos tests peuvent être forkée).</p>
<p>Alors j&#8217;ai essayé de récupérer les informations pour récupérer les informations de la VM qui tourne, mais bon on tombe dans des classes <strong>sun</strong>, j&#8217;ai préféré ne pas continuer sur ce chemin semé d&#8217;embûches, sans compter sur la faiblesse de cette approche.</p>
<p>Bref en relisant les articles de Khanh sur JMX, j&#8217;ai vu quelque chose d&#8217;intéressant <code>JMXConnectorServerFactory</code>. Cette classe permet donc de créer un <code>JMXConnectorServer</code> avec l&#8217;URL qu&#8217;on lui spécifie et d&#8217;un <code>MBeanServer</code>. A noter que cette URL doit respecter un certain formalisme tel que la javadoc l&#8217;indique : <code>service:jmx:<em>protocol</em>:<em>remainder</em></code>.</p>
<p>Le protocole ne peut pas être n&#8217;importe quoi, il faut qu&#8217;il y ait le bon service enregistré pour qu&#8217;il soit géré. Dans notre cas RMI est standard, c&#8217;est donc le protocole que je prendrai. Pour le remainder, il s&#8217;agit plus d&#8217;une partie d&#8217;une URL, je vous laisse voir la Javadoc de <code>JMXServiceUrl</code> à ce sujet, mais dans les grandes lignes la forme doit être la suivante : <code>//[host[:port]][url-path]</code></p><pre class="crayon-plain-tag">JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(
    new JMXServiceURL(&amp;quot;service:jmx:rmi://&amp;quot;),
    null,
    mBeanServer
);

connectorServer.start();</pre><p>Hop dans le code précédent, on a créé puis démarrer notre <code>JMXConnectorServer</code>. Il n&#8217;y a plus qu&#8217;à se connecter dessus de manière standard :<br />
Je vais utiliser <code>connectorServer.getJMXServer()</code> pour récupérer l&#8217;URL du service, il y a une raison à cela, c&#8217;est que comme l&#8217;indique la javadoc, l&#8217;URL passée pour la création du <code>JMXConnectorServer</code> peut être légèrement modifiée par celui-ci, il faut donc récupérer la nouvelle URL.</p><pre class="crayon-plain-tag">JMXConnector jmxConnetor = JMXConnectorFactory.connect(connectorServer.getJMXServiceUrl());
MBeanServerConnection connection = jmx.getgetMBeanServerConnection();</pre><p>Et voilà vous avez accès à une <code>MBeanServerConnection</code>, qui vit dans la JVM locale, mais qui utilise RMI pour communiquer avec le <code>MBeanServer</code>, du coup vous êtes nettement plus proches des conditions du code de production et c&#8217;est ce qui nous intéresse dans cet article.</p>
<p>Pour référence les articles de Khanh, et en français s&#8217;il vous plait <img src="https://s.w.org/images/core/emoji/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> :</p>
<ul>
<li>Partie 1 : <a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html">http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html</a></li>
<li>Partie 2 : <a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html">http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html</a></li>
<li>Partie 3 : <a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html">http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html</a></li>
<li>Partie 4 : <a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html">http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html</a></li>
<li>Partie 5 : <a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html">http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html</a></li>
<li>Partie 6 : <a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html">http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html</a></li>
<li>Partie 7 : <a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html">http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html</a></li>
<li>Partie 8 : <a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html">http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html</a></li>
</ul>
<p>Quelques liens javadoc :</p>
<ul>
<li><a href="http://download.oracle.com/javase/6/docs/api/javax/management/remote/JMXConnectorFactory.html">JMXConnectorFactory</a></li>
<li><a href="http://download.oracle.com/javase/6/docs/api/javax/management/remote/JMXConnectorServerFactory.html">JMXConnectorServerFactory</a></li>
<li><a href="http://download.oracle.com/javase/6/docs/api/javax/management/remote/JMXServiceURL.html">JMXServiceURL</a></li>
<li><a href="http://download.oracle.com/javase/6/docs/api/javax/management/remote/JMXConnectorServer.html">JMXConnectorServer</a></li>
</ul>
<p>Enfin je me suis créé une petite classe de commodité qui permet de créé facilement un loopback pour les TU :</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.arkey.fr/2011/10/14/tester-votre-code-jmx-dans-des-conditions-pseudo-reelle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
