<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Laurent Pellegrino</title>
    <description></description>
    <link>https://pellegrino.link/</link>
    <atom:link href="https://pellegrino.link/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 03 May 2025 14:54:58 +0000</pubDate>
    <lastBuildDate>Sat, 03 May 2025 14:54:58 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Scaleway Object Storage using Java</title>
        <description>&lt;p&gt;Until recently, I used Google Cloud Storage to periodically store and retrieve 
a few TB of data. Although Google services and their premium network 
solution are by far the best solution I worked with (the bandwidth and latency 
are just incredible from anywhere to anywhere in the World), the price is too
expensive for my use case.&lt;/p&gt;

&lt;p&gt;Looking at affordable solutions, and after reviewing a dozen solutions going 
from Digital Ocean, Hetzner, OVH, and more, I decided to go with Scaleway.&lt;/p&gt;

&lt;p&gt;Why Scaleway? their object storage solution is cheap (I divided the bill by
almost 100 compared to Google Cloud Storage), you have great 
configuration options to manage privacy, lifecycle rules, and up to 100Gbp/s 
bandwidth. Furthermore, despite their offer uses the public Internet, the 
peering is quite good Worldwide, meaning you can expect a good bandwidth even if
you download or upload from Australia or the US.&lt;/p&gt;

&lt;p&gt;However, nothing is perfect. The Scaleway documentation is quite minimal. There
are no official client libraries, nor examples of basic operations
like downloading an object from a Scaleway bucket in Java. That’s the purpose of
this blog post.&lt;/p&gt;

&lt;p&gt;Scaleway mimics the Amazon S3 interface and the Amazon SDK is configurable 
enough to be used with Scaleway. To use Scaleway Object Storage in Java, you
need to first import the Amazon SDK as a dependency.&lt;/p&gt;

&lt;p&gt;Here is the dependency to use if you are using Gradle:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;implementation&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;software.amazon.awssdk:s3:2.16.74&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Did you notice Amazon owns the domain &lt;em&gt;amazon.software&lt;/em&gt;? yes, &lt;em&gt;software&lt;/em&gt; is a 
top-level domain.&lt;/p&gt;

&lt;p&gt;The next step is to create a client instance:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;S3Client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;region&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Region&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fr-par&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;endpointOverride&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://s3.fr-par.scw.cloud&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;credentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;StaticCredentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;AwsBasicCredentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accessKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the code snippet above, &lt;em&gt;accessKey&lt;/em&gt; and &lt;em&gt;secretKey&lt;/em&gt; are your credentials to
get from the Scaleway dashboard.&lt;/p&gt;

&lt;p&gt;Once you have a client instance, it is really easy to interact with the Object
Storage service. For instance, here is an example to retrieve an object file as 
an &lt;em&gt;InputStream&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GetObjectRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objectRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;GetObjectRequest&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;path/to/your/object/file&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bucket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;your-scaleway-bucket&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is a link to Gist for a basic class example:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/lpellegr/e2a05f24181c33a65467fbc189a2e115&quot;&gt;https://gist.github.com/lpellegr/e2a05f24181c33a65467fbc189a2e115&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 31 May 2021 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2021/05/31/scaleway-object-storage-s3-java-library.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2021/05/31/scaleway-object-storage-s3-java-library.html</guid>
        
        <category>Scaleway</category>
        
        <category>Object Storage</category>
        
        <category>Java</category>
        
        <category>S3</category>
        
        
      </item>
    
      <item>
        <title>Migrating to AOF from RDB with Redis</title>
        <description>&lt;p&gt;You are using Redis with RDB persistence enabled for legacy reasons, a specific
use case or simply because that’s the default persistence method and you would like 
to switch to AOF persistence by default.&lt;/p&gt;

&lt;p&gt;As a Redis user, you will most probably encounter this situation a day. You are
wondering what is the best approach to migrate from one persistence format to
another or to use both?&lt;/p&gt;

&lt;p&gt;Unfortunately, Redis requires to restart your server to enable AOF persistence.
Here is a 4 steps process to reduce downtime:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a copy of your existing RDB backup file.&lt;/li&gt;
  &lt;li&gt;From a Redis client trigger the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bgrewriteaof&lt;/code&gt;. This will create
a backup file (named by default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;appendonly.aof&lt;/code&gt;) using the AOF format.&lt;/li&gt;
  &lt;li&gt;Edit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redis.conf&lt;/code&gt; to enable AOF persistance with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;appendonly yes&lt;/code&gt;
configuration line.&lt;/li&gt;
  &lt;li&gt;Restart your Redis server.&lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Wed, 10 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2020/06/10/2020-redis-persistence-migrating-rdb-to-aof.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2020/06/10/2020-redis-persistence-migrating-rdb-to-aof.html</guid>
        
        <category>Redis</category>
        
        <category>Persistence</category>
        
        <category>Migration</category>
        
        
      </item>
    
      <item>
        <title>Signing Nvidia proprietary driver on Fedora</title>
        <description>&lt;p&gt;Two weeks ago I have upgraded my machine to Fedora 23. I fought a bit with the
installation of Nvidia proprietary driver. The main reason was that new kernel
modules to load need to be signed with a key accepted by &lt;a href=&quot;https://docs.fedoraproject.org/en-US/Fedora/23/html/System_Administrators_Guide/sect-signing-kernel-modules-for-secure-boot.html&quot;&gt;Secure Boot&lt;/a&gt;.
Below are steps I have followed to achieve this configuration.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;creating-new-x509-key-pair&quot;&gt;Creating New X.509 Key Pair&lt;/h1&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.openssl.org&quot;&gt;openssl&lt;/a&gt; tool can be used to generate a public
and private X.509 key pair that will be used to sign a kernel module after it
has been built.&lt;/p&gt;

&lt;p&gt;First, it is recommended to create a configuration file to pass parameters.
Hereafter is an example named &lt;em&gt;x509-configuration.ini&lt;/em&gt;. The values starting by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YOUR_&lt;/code&gt; need to be replaced by your own data:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[ req ]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;default_bits&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;4096&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;distinguished_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;req_distinguished_name&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;no&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;string_mask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;utf8only&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;x509_extensions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;myexts&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;YOUR_USERNAME&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;CN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;YOUR_USERNAME&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;emailAddress&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;YOUR_EMAIL_ADDRESS&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[ myexts ]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;basicConstraints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;critical,CA:FALSE&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;keyUsage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;digitalSignature&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;subjectKeyIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;hash&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;authorityKeyIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;keyid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, key pair can be generated as follows:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openssl req &lt;span class=&quot;nt&quot;&gt;-x509&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-new&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nodes&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-utf8&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-days&lt;/span&gt; 36500 &lt;span class=&quot;nt&quot;&gt;-batch&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-config&lt;/span&gt; x509-configuration.ini &lt;span class=&quot;nt&quot;&gt;-outform&lt;/span&gt; DER &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; public_key.der &lt;span class=&quot;nt&quot;&gt;-keyout&lt;/span&gt; private_key.priv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output are two files: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public_key.der&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private_key.priv&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;enrolling-public-key&quot;&gt;Enrolling Public Key&lt;/h1&gt;

&lt;p&gt;At boot, the kernel loads Secure Boot db key database into system keyring. Since
this last is used to check which kernel modules can be loaded, the public key
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public_key.der&lt;/code&gt; needs to be enrolled in this database in order to accept new
modules signed with our private key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private_key.priv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Usually, this operation can be achieved with &lt;em&gt;mokutil&lt;/em&gt; Fedora userspace utility:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mokutil &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; mpublic_key.der
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, this utility was not working for me. I was always getting
&lt;em&gt;Failed to enroll new keys&lt;/em&gt;. Hopefully, it is possible to enroll a new key
from the UEFI interface, directly.&lt;/p&gt;

&lt;p&gt;First, copy file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public_key.der&lt;/code&gt; on an USB key, then restart your machine and
press the appropriate key to access your UEFI interface.&lt;/p&gt;

&lt;p&gt;In my case the right key is &lt;em&gt;F2&lt;/em&gt;. Once pressed, the UEFI interface of my
&lt;em&gt;SABERTOOTH Z97 MARK 1&lt;/em&gt; motherboard is displayed. To configure Secure Boot keys,
I clicked on &lt;em&gt;Advanced Mode&lt;/em&gt;, &lt;em&gt;Boot&lt;/em&gt;, &lt;em&gt;Secure Boot&lt;/em&gt; and &lt;em&gt;Key Management&lt;/em&gt;.
From the panel I selected &lt;em&gt;Append default DB keys&lt;/em&gt;, answered &lt;em&gt;No&lt;/em&gt; to the question
that asked if I wanted to append default DB keys. This way it asked me from
where I wanted to load keys. It allowed me to select my public key from USB key.&lt;/p&gt;

&lt;p&gt;Once loaded, you can restart your machine. All new kernel modules signed with
the private key generated previously should be loaded with success by the
kernel.&lt;/p&gt;

&lt;h1 id=&quot;signing-kernel-module&quot;&gt;Signing kernel module&lt;/h1&gt;

&lt;p&gt;Move to the folder that contains the nvidia kernel module compiled. If
proprietary driver was installed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf&lt;/code&gt; the location should be
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/modules/$(uname -r)/extra/nvidia-340xx/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this location, two files should be available: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvidia.ko&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvidia-uvm.ko&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Signing both modules is as simple as follows (assuming package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel-devel&lt;/code&gt;
is installed):&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;perl /usr/src/kernels/&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;/scripts/sign-file sha256 ~/private_key.priv  ~/public_key.der  nvidia.ko
perl /usr/src/kernels/&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;/scripts/sign-file sha256 ~/private_key.priv  ~/public_key.der  nvidia-uvm.ko
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, module can be loaded with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insmod&lt;/code&gt; and loaded modules listed with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listmod&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2015/11/29/signing-nvidia-proprietary-driver-on-fedora.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2015/11/29/signing-nvidia-proprietary-driver-on-fedora.html</guid>
        
        <category>Secure Boot</category>
        
        <category>Nvidia proprietary driver</category>
        
        <category>Fedora 23</category>
        
        <category>Signing kernel module</category>
        
        
      </item>
    
      <item>
        <title>String concatenation with Java 8</title>
        <description>&lt;p&gt;String concatenation is one of the most well-known caveats in Java. Almost all experienced Java developers have already heard or read explanations about when to use &lt;em&gt;String&lt;/em&gt; vs &lt;em&gt;StringBuilder&lt;/em&gt;/&lt;em&gt;StringBuffer&lt;/em&gt; for concatenating Strings.&lt;/p&gt;

&lt;p&gt;These last months I gave some interviews for a Java position in the company where I work. One of the exercises that candidates sometimes have to work on requires concatenating Strings in a for loop. Obviously, as a &lt;del&gt;pervert&lt;/del&gt; programmer, I like to ask people what they think about the performance of the code they write and how it could be improved. The answers were really surprising, especially about String concatenation. Although some explanations were not really convincing, they let me doubt whether using &lt;em&gt;StringBuilder&lt;/em&gt;/&lt;em&gt;StringBuffer&lt;/em&gt; is still required with a recent Java virtual machine.  For this reason, I decided to do some investigations.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;understanding-the-issue&quot;&gt;Understanding the issue&lt;/h1&gt;

&lt;p&gt;In Java String objects are immutable. It means that any operation on a String object will not alter the content of the object but create a new one with the transformed value.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For instance, the piece of code introduced above is a simple loop that iterates 1M times and concatenates the String “some more data” to the &lt;em&gt;result&lt;/em&gt; variable at each iteration. However, using the &lt;em&gt;+&lt;/em&gt; operator (which is strictly equivalent to &lt;em&gt;result = result + “some more data”&lt;/em&gt; in our example) or even &lt;a href=&quot;http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#concat-java.lang.String-&quot;&gt;String#concat(String)&lt;/a&gt; does not mean that internally data is sticked at the end of the &lt;em&gt;result&lt;/em&gt; variable in one step. It is not possible since String objects are immutable.&lt;/p&gt;

&lt;p&gt;Under the hood, many operations occur. First, a new array of characters is allocated with a size that fits the existing value contained by the &lt;em&gt;result&lt;/em&gt; variable but also the payload that is appended. Then, their value is copied to the new array instance and a new String object is created from the array. Finally, the new String instance replaces the one already assigned to the &lt;em&gt;result&lt;/em&gt; variable, and this last is marked for &lt;a href=&quot;http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot;&gt;garbage collection&lt;/a&gt; since it is no longer referenced by a variable.&lt;/p&gt;

&lt;p&gt;This sequence of actions means that as the &lt;em&gt;result&lt;/em&gt; variable grows, the amount of data to copy each time grows, and the time to complete the operation too. Simple mathematics can be applied to estimate the complexity of the previous piece of code in terms of copy required.&lt;/p&gt;

&lt;p&gt;At the first iteration, $14$ characters are copied to an array of characters of size $0 + 14$. The second iteration copies $28$ characters to an array of characters of size $14 + 14$. Then, at the third iteration, an array of size $28 + 14$ is allocated and $36$ characters copied into, and so on and so forth.&lt;/p&gt;

&lt;p&gt;In summary, the number of copy required for &lt;em&gt;n&lt;/em&gt; iterations is equals to:&lt;/p&gt;

\[\sum_{i=0}^{n-1} 14 \times i = 7n(n-1) = 7n^2-7n\]

&lt;p&gt;If you already took a complexity class, you probably remember that $7n^2-7n$ means that your algorithm complexity is in $O(n^2)$, namely quadratic.&lt;/p&gt;

&lt;h1 id=&quot;stringbuilderstringbuffer-to-the-rescue&quot;&gt;StringBuilder/StringBuffer to the rescue&lt;/h1&gt;

&lt;p&gt;As explained previously, the complexity of a simple Java loop concatenating Strings using the “+” operator is quadratic. That’s not good, especially for a simple operation such as concatenation. Let’s say that copying 10 characters takes 10ms, then it means that copying 100 characters will take 1s. In other words, a problem 10 times larger takes 100 times more work.&lt;/p&gt;

&lt;p&gt;Hopefully, a solution to this issue exists. It consists in using the &lt;a href=&quot;http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html&quot;&gt;StringBuilder&lt;/a&gt; or &lt;a href=&quot;http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html&quot;&gt;StringBuffer&lt;/a&gt; class. The main difference between both is that the last is &lt;a href=&quot;https://en.wikipedia.org/wiki/Thread_safety&quot;&gt;thread-safe&lt;/a&gt; whereas the first is not. Below is an example solving the issue explained previously:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see an instance of &lt;em&gt;StringBuilder&lt;/em&gt;/&lt;em&gt;StringBuffer&lt;/em&gt; like a mutable String object. The &lt;em&gt;append&lt;/em&gt; call alters the state of the object, thus avoiding several copies.&lt;/p&gt;

&lt;p&gt;Internally, &lt;em&gt;StringBuilder&lt;/em&gt; makes use of a resizable array and an index that indicates the position of the last cell used in the array. When a new String is appended, its characters are copied to the end of the array and the index shifted to the right. If the internal array is full, its size is doubled (to be exact, if the array size is $x$, then the new size will be &lt;a href=&quot;http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e52f33586140/src/share/classes/java/lang/AbstractStringBuilder.java#l128&quot;&gt;$2x+2$&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So, why is this manner to proceed faster than the one used with the &lt;em&gt;+&lt;/em&gt; operator? The reason lies in the fact that array expansion and the associated copy of characters is performed occasionally, when the array is full. Asymptotically speaking, by using $2x+2$ as an expansion factor, the resize operation does not occur so often and StringBuilder#append(String) thus &lt;a href=&quot;http://www.quora.com/What-is-the-complexity-of-Java-StringBuffer-append&quot;&gt;takes O(1) amortized time&lt;/a&gt;. Consequently, the whole loop has a complexity in $O(n)$.&lt;/p&gt;

&lt;h1 id=&quot;looking-at-the-bytecode&quot;&gt;Looking at the Bytecode&lt;/h1&gt;

&lt;p&gt;What I explained is maybe boring but an interesting question is &lt;em&gt;does the previous explanations still hold with Java 8&lt;/em&gt;? I mean is it still required to use &lt;em&gt;StringBuilder&lt;/em&gt;/&lt;em&gt;StringBuffer&lt;/em&gt; or some magic tricks are applied with the &lt;em&gt;+&lt;/em&gt; operator? since going in deep in the &lt;a href=&quot;http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/&quot;&gt;source code of JDK 8&lt;/a&gt; would require a few weeks, an alternative to answer the question is to look at the bytecode generated by the compiler.&lt;/p&gt;

&lt;p&gt;Let’s start with a simple example:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticStringConcatenation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A human-readable representation of the bytecode that is generated by &lt;em&gt;javac&lt;/em&gt; can be obtained for the Java class above. It requires first to generate the class file associated with the source code, then disassembling this last file using the &lt;em&gt;javap&lt;/em&gt; command. Since the previous code, along with all other resources introduced in this post are available on Github in a &lt;a href=&quot;https://github.com/lpellegr/experiments/tree/master/java/string-concatenation&quot;&gt;dedicated Gradle project&lt;/a&gt;, both steps can be reproduced as follows once the project has been cloned:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gradlew&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;gt;-&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;StaticStringConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Compiled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;StaticStringConcatenation.java&quot;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticStringConcatenation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StaticStringConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;Code:&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aload_0&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Push &apos;this&apos; on to the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokespecial&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke Object class constructor&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// pop &apos;this&apos; ref from the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Return from constructor&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]);&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;Code:&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldc&lt;/span&gt;           &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Load constant #2 on to the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;astore_1&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// Create local var from stack (pop #2)&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;           &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push new StringBuilder ref on stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;// Duplicate value on top of the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokespecial&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder constructor&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// pop object reference&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aload_1&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Push local variable containing #2&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke method StringBuilder.append()&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// pop obj reference + parameter&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// push result (StringBuilder ref)&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldc&lt;/span&gt;           &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push &quot;some more data&quot; on the stack&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder.append&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// pop twice, push result&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder.toString:();&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;astore_1&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// Create local var from stack (pop #6)&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getstatic&lt;/span&gt;     &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push value System.out:PrintStream&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aload_1&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Push local variable containing #6&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke method PrintStream.println()&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// pop twice (object ref + parameter)&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Return void from method&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the output above, comments have been manually edited to get a text that fits on the page but also to clarify the bytecode &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings&quot;&gt;instructions&lt;/a&gt;. In consequence, it’s normal if you get more obscure comment messages when you try to execute the previous commands.&lt;/p&gt;

&lt;p&gt;Before continuing, some explanations about the JVM internals are required. The Java Virtual Machine (JVM) is an abstract machine that provides a runtime environment in which Java bytecode can be executed. To this aim, the JVM is &lt;a href=&quot;http://blog.jamesdbloom.com/JVMInternals.html&quot;&gt;made of several components&lt;/a&gt; including among others:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;an &lt;em&gt;Operand Stack&lt;/em&gt; (named &lt;em&gt;stack&lt;/em&gt; in the following) that aims to execute bytecode instructions similarly to registers with a CPU;&lt;/li&gt;
  &lt;li&gt;a &lt;em&gt;Run Time Constant Pool&lt;/em&gt; (referred to as &lt;em&gt;constant pool&lt;/em&gt; below) to maintain a per-type constant pool;&lt;/li&gt;
  &lt;li&gt;a &lt;em&gt;Heap&lt;/em&gt; that is used to allocate class instances and arrays at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output produced by &lt;em&gt;javap&lt;/em&gt; displays the bytecode instructions using JVM opcodes (&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.4-mnemonic&quot;&gt;mnemonics&lt;/a&gt; to be exact). For instance, &lt;em&gt;aload_0&lt;/em&gt; is the first opcode executed when the constructor of the class &lt;em&gt;StaticStringConcatenation&lt;/em&gt; is invoked. Its purpose is to push ‘this’ (the reference to the local object created in the heap) on to the stack. Then, &lt;em&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokespecial&quot;&gt;invokespecial&lt;/a&gt;&lt;/em&gt;  invokes the instance initialization method based on the object reference in the stack (and thus pop the reference from the stack to consume it). The exact class and method to execute is identified in this example by &lt;em&gt;#1&lt;/em&gt; in the constant pool. Constant pool values associated with an identifier can be displayed with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v&lt;/code&gt; option of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;javap&lt;/code&gt;. Finally, &lt;em&gt;return&lt;/em&gt; terminates the execution of the constructor.&lt;/p&gt;

&lt;p&gt;In summary, the JVM makes use of opcodes to execute basic instructions. The execution and pipelining of several instructions is made possible through an intermediary which is the stack. Values are pushed to and/or pop from when opcodes are executed.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at the instructions and their associated comments for the &lt;em&gt;main&lt;/em&gt; method. At code &lt;em&gt;7&lt;/em&gt;, a new instance of &lt;em&gt;StringBuilder&lt;/em&gt; is created, then at code &lt;em&gt;11&lt;/em&gt; the empty String is appended to the &lt;em&gt;StringBuilder&lt;/em&gt; object by using the append method. Similarly, at code &lt;em&gt;16&lt;/em&gt; the String “some more data” is concatenated before retrieving a String representation with the help of the &lt;em&gt;toString&lt;/em&gt; method (code 19). Finally, once the reference to the static field PrintStream is fetched (code 8), the value is displayed on the standard output (code 27).&lt;/p&gt;

&lt;p&gt;If you have followed what I said before, you may ask why is an instance of StringBuilder created? after all the code source has no reference to &lt;em&gt;StringBuilder&lt;/em&gt;. The answer lies in the fact that all of the substrings building the final String are known at compile time. In this specific case, the Java compiler (written by people who know the drawback of the &lt;em&gt;+&lt;/em&gt; operator) optimizes the bytecode that is generated. In our case, String concatenation with the &lt;em&gt;+&lt;/em&gt; operator is replaced by:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This optimization is known as a static string concatenation optimization and is available since Java 5.&lt;/p&gt;

&lt;p&gt;So, does it means that all the previous explanations about the cost of the &lt;em&gt;+&lt;/em&gt; operator no longer hold? at this point it’s true for &lt;em&gt;static&lt;/em&gt; string concatenation. However, investigations are still required with &lt;em&gt;dynamic&lt;/em&gt; string concatenation.&lt;/p&gt;

&lt;h1 id=&quot;going-further-with-dynamic-string-concatenation&quot;&gt;Going further with dynamic string concatenation&lt;/h1&gt;

&lt;p&gt;Dynamic string concatenation refers to the concatenation of substrings whose the result is known at runtime only. This is for instance the case for substrings appended to a String in a for loop:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DynamicStringConcatenation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Below is the disassembled human readable bytecode:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DynamicStringConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Compiled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DynamicStringConcatenation.java&quot;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DynamicStringConcatenation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DynamicStringConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;Code:&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aload_0&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Push &apos;this&apos; on to the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokespecial&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke Object class constructor&lt;/span&gt;
                           &lt;span class=&quot;c1&quot;&gt;// pop &apos;this&apos; ref from the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Return from constructor&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]);&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;Code:&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldc&lt;/span&gt;            &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Load constant #2 on to the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;astore_1&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Create local var from stack, pop #2&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iconst_0&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Push value 0 onto the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;istore_2&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Pop value and store it in local var&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iload_2&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Push local var 2 on to the stack&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i2d&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Convert int to double on&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// top of stack (pop + push)&lt;/span&gt;
       &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldc2_w&lt;/span&gt;         &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push constant 10e6 on to the stack&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dcmpg&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;// Compare two doubles on top of stack&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// pop twice, push result: -1, 0 or 1&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifge&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// if value on top of stack is greater&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// than or equal to 0 (pop once)&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// branch to instruction at code 40&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;            &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push new StringBuilder ref on stack&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Duplicate value on top of the stack&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokespecial&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder constructor&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// pop object reference&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aload_1&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Push local var 1 (empty String)&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// on to the stack&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder.append&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// pop obj ref + param, push result&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldc&lt;/span&gt;            &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push &quot;some more data&quot; on the stack&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder.append&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// pop obj ref + param, push result&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke StringBuilder.toString&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// pop object reference&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;astore_1&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Create local var from stack (pop)&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iinc&lt;/span&gt;         &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Increment local variable 2 by 1&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt;            &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Move to instruction at code 5&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getstatic&lt;/span&gt;     &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Push value System.out:PrintStream&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aload_1&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Push local var 1 (result String)&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokevirtual&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Invoke method PrintStream.println()&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// pop twice (object ref + parameter)&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// Return void from method&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you look quickly at the instructions and comments, you can see there are some references to &lt;em&gt;StringBuilder&lt;/em&gt;. However, it does not mean that, in this context, String concatenation is “optimized”. A closer look (by drawing for instance how the &lt;em&gt;stack&lt;/em&gt; evolves) will show you that a new &lt;em&gt;StringBuilder&lt;/em&gt; instance is created per iteration. That’s because optimization for static string concatenation is applied in the body of the loop but not outside. The compiler cannot compute the concatenating result without executing the instructions, which is not its role.&lt;/p&gt;

&lt;p&gt;Supposing that the source code associated with the bytecode of the class &lt;em&gt;DynamicStringConcatenation&lt;/em&gt; has to be displayed, then this one would look as follows:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Based on the code, it means that explanations given in &lt;a href=&quot;#understanding-the-issue&quot;&gt;Understanding the issue&lt;/a&gt; section about the performance issue still hold for dynamic String concatenation. Using the &lt;em&gt;+&lt;/em&gt; operator for concatenating substrings to a String defined outside the body of the loop will cause severe performance degradations.
Although &lt;em&gt;StringBuilder&lt;/em&gt; is used by the compiler, an instance must be created at each iteration and the characters inside the &lt;em&gt;result&lt;/em&gt; variable copied to the &lt;em&gt;StringBuilder&lt;/em&gt; instance before appending “some more data” and returning a String representation with &lt;em&gt;toString&lt;/em&gt;. This last incurring another copy of characters contained by the &lt;em&gt;StringBuilder&lt;/em&gt; instance.&lt;/p&gt;

&lt;p&gt;One solution is to manually create a &lt;em&gt;StringBuilder&lt;/em&gt; instance outside the loop:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Besides, if you know in advance the total number of characters that will be appended to the &lt;em&gt;StringBuilder&lt;/em&gt; instance, you can pass this value to the constructor. It will prevent some resize operations and thus give better results.&lt;/p&gt;

&lt;h1 id=&quot;assessing-performance-with-micro-benchmarks&quot;&gt;Assessing performance with micro-benchmarks&lt;/h1&gt;

&lt;p&gt;Until now it has been clarified that dynamic string concatenation with the &lt;em&gt;+&lt;/em&gt; operator is not optimized in Java 8 by the compiler, similarly to previous Java versions. However, nothing can be concluded yet. Indeed, the JVM is highly optimized and optimizations which are not made at compile time can be performed at runtime by the &lt;a href=&quot;https://en.wikipedia.org/wiki/Just-in-time_compilation&quot;&gt;Just-In-Time (JIT)&lt;/a&gt; compiler.&lt;/p&gt;

&lt;p&gt;The purpose of the JIT is twofold. First it is used to analyze method calls in background and to compile the bytecode of methods that are frequently used into native CPU instructions. Thus, once a method has been compiled, its native form is used, which avoids an indirection with the interpretation of the bytecode. Second, the JIT can analyze dynamic runtime information to make optimizations that a compiler cannot. For example, inlining functions that are used frequently, eliminating dead code, removing locks if monitor is not reachable from other threads, etc. This way, a code written in Java may sometimes run faster than its equivalent in C.&lt;/p&gt;

&lt;p&gt;Since the Java HotSpot Performance Engine (JVM) apply many optos, maybe some magic tricks with dynamic string concatenation occurs at runtime. To check this assumption, the best is to &lt;a href=&quot;http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/dae2d83e0ec2/src/share/vm/opto/stringopts.cpp&quot;&gt;look at the implementation&lt;/a&gt; but it would require too much time without the guarantee not to forget to look at a piece of code. Another solution is to write micro-benchmarks to compare the time required to concatenate Strings in a for loop using the &lt;em&gt;+&lt;/em&gt; operator vs an instance of &lt;em&gt;StringBuilder&lt;/em&gt; .&lt;/p&gt;

&lt;p&gt;Writing micro-benchmarks, especially in Java is not easy. As explained before, the JIT is performing many optimizations in a transparent manner. It implies to be aware of its optimizations, the effects of initialization, recompilation, etc. to write a meaningful micro-benchmark. Otherwise, you might measure something completely wrong. Hopefully, some libraries exist to help in this task. Especially, &lt;a href=&quot;http://openjdk.java.net/projects/code-tools/jmh/&quot;&gt;Java Microbenchmark Harness (JMH)&lt;/a&gt; which has the advantage to be written by &lt;del&gt;Russians&lt;/del&gt; people working on the JIT implementation.&lt;/p&gt;

&lt;p&gt;Below are the micro-benchmarks written to assess String concatenation performance using JMH:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Scope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@BenchmarkMode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SingleShotTime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Measurement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batchSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Warmup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batchSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Fork&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringConcatenationBenchmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stringConcat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuffer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stringBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Setup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Level&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Iteration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stringConcat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stringBuilder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stringBuffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Benchmark&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stringConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Benchmark&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stringConcatConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stringConcat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stringConcat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Benchmark&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stringBuilderConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Benchmark&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stringBufferConcatenation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stringBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some more data&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The previous class is &lt;a href=&quot;https://github.com/lpellegr/experiments/blob/master/java/string-concatenation/src/jmh/java/link/pellegrino/string_concatenation/StringConcatenationBenchmark.java&quot;&gt;available on Github&lt;/a&gt; packaged in a gradle project. If you want to run micro-benchmarks on your side, you can as follows once the project is cloned:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./gradlew jmh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Briefly speaking, iterations are made by JMH using the &lt;em&gt;batchSize&lt;/em&gt; parameter with &lt;em&gt;Measurement&lt;/em&gt; and &lt;em&gt;Warmup&lt;/em&gt; annotations. This last annotation is useful to perform runs that aim to warm the JVM so that JIT optimizations are in place when measurements are made. More information about JMH and its annotations can be found on &lt;a href=&quot;http://java-performance.info/jmh/&quot;&gt;java-performance.info&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The next figure sketches the trends:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.google.com/spreadsheets/d/1dV4Pbe2_ZCsc9TDBYsN9u69a2a3xSjCAzxKR7I6fxzg/edit?usp=sharing&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://docs.google.com/spreadsheets/d/1dV4Pbe2_ZCsc9TDBYsN9u69a2a3xSjCAzxKR7I6fxzg/pubchart?oid=1847999196&amp;amp;format=image&quot; alt=&quot;tre&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;em&gt;StringBuilder&lt;/em&gt;/&lt;em&gt;StringBuffer&lt;/em&gt; clearly outperforms other approaches that use the &lt;em&gt;+&lt;/em&gt; operator or &lt;em&gt;String#concat(String)&lt;/em&gt; for dynamic String concatenation. Although &lt;em&gt;String#concat(String)&lt;/em&gt; scales in a similar manner as the method based on the &lt;em&gt;+&lt;/em&gt; operator, the difference of performance between both may be explained by the fact that no transformation is performed by the compiler for &lt;em&gt;String#concat(String)&lt;/em&gt;. This last does not require to create multiple StringBuilder instances while avoiding the extra copy incurred by the call to &lt;em&gt;StringBuilder#toString()&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;In summary, Java 8 seems not to introduce new optimizations for String concatenation with the &lt;em&gt;+&lt;/em&gt; operator. It means that using &lt;em&gt;StringBuilder&lt;/em&gt; manually is still required for specific cases where the compiler or the JIT is not applying magic tricks. For instance, when a lot of substrings are concatenated to a String variable defined outside the scope of a loop.&lt;/p&gt;

&lt;p&gt;The reason for not optimizing automatically all String concatenations is still a bit obscure to me. Probably, too much information and effort are required to handle  all possible cases safely. After all, that’s also a good point to make programmers think about what they write.&lt;/p&gt;

&lt;p&gt;If you are interested in String optimizations in Java and their associated methods, I recommend having a look at the interesting &lt;a href=&quot;http://shipilev.net/talks/joker-Oct2014-string-catechism.pdf&quot;&gt;slides made by Aleksey Shipilёv&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sat, 22 Aug 2015 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2015/08/22/string-concatenation-with-java-8.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2015/08/22/string-concatenation-with-java-8.html</guid>
        
        <category>Java</category>
        
        <category>String Concatenation</category>
        
        <category>Dynamic String Concatenation</category>
        
        <category>Static String Concatenation</category>
        
        <category>StringBuilder</category>
        
        <category>StringBuffer</category>
        
        <category>Javap</category>
        
        <category>JIT</category>
        
        <category>Just-In-Time compiler</category>
        
        <category>JMH</category>
        
        
      </item>
    
      <item>
        <title>Brace expansion with Unix Shells</title>
        <description>&lt;p&gt;Recently, I discovered a great feature that most of recent &lt;a href=&quot;https://en.wikipedia.org/wiki/Unix_shell&quot;&gt;Shells&lt;/a&gt; support. It is named &lt;em&gt;brace expansion&lt;/em&gt;. I used it occasionally but without knowing how it behaves and what was its power.&lt;/p&gt;

&lt;p&gt;Below is an example:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;I&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;like,love,hate&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;chocolate
Ilikechocolate Ilovechocolate Ihatechocolate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;!--more--&gt;

&lt;p&gt;In this example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{like,love,hate}&lt;/code&gt; has a special meaning: it’s a list of String elements delimited by braces whose elements are expanded with the word it is attached with. As the output shows, once evaluated each String element creates a new word by replacing the list by its value.&lt;/p&gt;

&lt;p&gt;Ok, that’s interesting but could it be used with a concrete example? the answer is yes. Let’s say that you need to create several folders in a same directory. The simplest manner I was aware of was to move to the desired folder and then to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir&lt;/code&gt; command for each directory:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; Images
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; Movies
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; Music
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The previous sequence of commands can be written pretty quickly but requires fingers gymnastic using keyboard shortcuts. With brace expansion, the previous example can be easily one-lined:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;Images,Movies,Music&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;nested-brace-expansion&quot;&gt;Nested brace expansion&lt;/h1&gt;

&lt;p&gt;Brace lists can be composed. For instance, the example above can be extended to create a hierarchy of folders quickly:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;Images/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;Cars,Family,House,Vacations&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,Movies,Music&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It will create the following folders in your home directory:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Images/Cars
Images/Family
Images/House
Images/Vacations
Movies
Music
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;generating-sequences&quot;&gt;Generating sequences&lt;/h1&gt;

&lt;p&gt;If you come from the imperative world (e.g. if you know for instance C or even used loops with Java), you are probably familiar with the 3 parameters loop control expression. You also know how boring it is to write, especially in Shell:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; i&amp;lt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; i++&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done
&lt;/span&gt;1
2
3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using brace sequences, the writing is shorter and more readable:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;1..3&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The general syntax for a sequence expression is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{START..END..INCREMENT}&lt;/code&gt; where &lt;em&gt;START&lt;/em&gt; and &lt;em&gt;END&lt;/em&gt; is a required integer or single character but &lt;em&gt;INCREMENT&lt;/em&gt; an optional integer value (default to 1). Such an expression generates a sequence of integers or characters by &lt;em&gt;INCREMENT&lt;/em&gt; step, starting from &lt;em&gt;START&lt;/em&gt; to &lt;em&gt;END&lt;/em&gt; included. This way, listing odd numbers between &lt;em&gt;9&lt;/em&gt; and &lt;em&gt;17&lt;/em&gt; is as simple as writing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;9..17..2&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
9 11 13 15 17
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While enumerating the alphabet is not more complex:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;a..z&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
a b c d e f g h i j k l m n o p q r s t u v w x y z
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;limitations&quot;&gt;Limitations&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;A valid brace expansion must contain at least a comma or a sequence expression.&lt;/li&gt;
  &lt;li&gt;Variable expansion works inside a brace list but not inside a sequence expression.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In conclusion, brace expansion is a really powerful feature that can save you time when you have to create directories, apply permissions, etc. Besides, the good news is that it is supported by almost all recent Shells.&lt;/p&gt;
</description>
        <pubDate>Sat, 07 Mar 2015 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2015/03/07/brace-expansion-with-unix-shells.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2015/03/07/brace-expansion-with-unix-shells.html</guid>
        
        <category>Brace expansion</category>
        
        <category>Bash</category>
        
        <category>Csh</category>
        
        <category>Ksh</category>
        
        <category>Shell</category>
        
        
      </item>
    
      <item>
        <title>Docker: SELinux is not supported with the BTRFS graph driver!</title>
        <description>&lt;p&gt;The first time I have succeeded to start a &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; container my reaction was: “Ouawwww, incredibly simple and fast!”. However, before having this feeling I have faced a failure while trying to start the docker daemon : “SELinux is not supported with the BTRFS graph driver!”.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;This is a &lt;a href=&quot;https://github.com/docker/docker/issues/7952&quot;&gt;known issue&lt;/a&gt; for systems running a BTRFS filesystem. Hopefully a workaround exists. It consists in editing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysconfig/docker&lt;/code&gt; to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OPTIONS=&apos;--selinux-enabled&apos;&lt;/code&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OPTIONS=&apos;--selinux-enabled=false&apos;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the update made, you have to restart the daemon.&lt;/p&gt;

</description>
        <pubDate>Wed, 11 Feb 2015 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2015/02/11/docker-selinux-is-not-supported-with-the-btrfs-graph-driver.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2015/02/11/docker-selinux-is-not-supported-with-the-btrfs-graph-driver.html</guid>
        
        <category>Btrfs</category>
        
        <category>Docker</category>
        
        <category>Fedora</category>
        
        <category>Linux</category>
        
        <category>Linux Containers</category>
        
        <category>LCX</category>
        
        <category>SeLinux</category>
        
        
      </item>
    
      <item>
        <title>&quot;Unfortunately, Launcher has stopped&quot; on Android</title>
        <description>&lt;p&gt;I am discovering Android emulators. My purpose is to automate screenshots capture for one of my apps (which will probably be the subject of another post). What was my astonishment when I started my first Android virtual device (running Lollipop) is that every time I was clicking on the app launcher icon I was getting “Unfortunately, Launcher has stopped.”&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;To fix the issue, my idea was to look at the logs provided by logcat with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb -e logcat&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; option is used in my case for directing the adb command to the only running emulator instance since I often let one or more physical devices plugged.&lt;/p&gt;

&lt;p&gt;Running the previous command displays many information but if you look at log messages corresponding to the time at which the app launcher icon was clicked, a really meaningful message is available:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;E/AndroidRuntime( 1794): FATAL EXCEPTION: main
E/AndroidRuntime( 1794): Process: com.android.launcher, PID: 1794
E/AndroidRuntime( 1794): java.lang.OutOfMemoryError: Failed to allocate a 13063692 byte allocation with 4194304 free bytes and 9MB until OOM
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Indeed, the issue comes from memory allocation. To fix the problem you simply have to increase the vm heap size associated to the virtual device (in my case to 256 from 64 MB). You can do it through the graphical interface (Android Studio or by executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;android avd&lt;/code&gt;). Another alternative is to edit the line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm.heapSize=64&lt;/code&gt; from the configuration file corresponding to the virtual device you have created. This file is located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.android/avd/AVD_NAME.avd/config.ini&lt;/code&gt; where AVD_NAME is the name of the virtual device you have created.&lt;/p&gt;
</description>
        <pubDate>Thu, 05 Feb 2015 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2015/02/05/unfortunately-launcher-has-stopped-on-android.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2015/02/05/unfortunately-launcher-has-stopped-on-android.html</guid>
        
        <category>ADB</category>
        
        <category>Android</category>
        
        <category>Android Virtual Device</category>
        
        <category>AVD</category>
        
        <category>Crash</category>
        
        <category>Error</category>
        
        <category>logcat</category>
        
        <category>Lollipop</category>
        
        <category>OutOfMemory</category>
        
        
      </item>
    
      <item>
        <title>Changing the I/O scheduler for a specific disk</title>
        <description>&lt;p&gt;Today, I have &lt;a href=&quot;https://wiki.archlinux.org/index.php/Solid_State_Drives#I.2FO_Scheduler&quot;&gt;read&lt;/a&gt; that switching the default I/O scheduler from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cqf&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;noop&lt;/code&gt; is benefit for Solid State Drives (SSD). Since I got an SSD recently, achieving this configuration was one of my concerns.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Changing permanently the I/O scheduler for a specific disk is really easy. It can be realized by executing the following shell command as root:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;echo {SCHEDULER-NAME} &amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/sys/block/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;DEVICE-NAME&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;/queue/scheduler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;where {SCHEDULER-NAME} is either the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfq&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;noop&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deadline&lt;/code&gt; and {DEVICE-NAME} the name of your device (e.g. sda). In my case, I used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;noop&lt;/code&gt; scheduler since it is the one that implies no reordering for I/O requests. Indeed, in contrary to Hard Disk Drives (HDD), SSD are not mechanical and don’t require to physically move heads for reads and writes. Consequently, reordering I/O requests is a waste of CPU time, which eventually decreases throughput and increases latency.&lt;/p&gt;

&lt;p&gt;Once applied you can check the change with:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;cat /sys/block/{DEVICE-NAME}/queue/scheduler
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, the change is lost after a reboot. If you are using systemd (e.g on Fedora 20), which is a system and service manager service, a specific unit may be written to apply your configuration at each reboot.&lt;/p&gt;

&lt;p&gt;You simply have to create a file in /etc/systemd/system/io-scheduler.service with the following content:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;[Unit]
Description=I/O Scheduler Setter
After=local-fs.target
[Service]
Type=oneshot
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;ExecStart=/bin/bash -c &apos;echo noop &amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/sys/block/sda/queue/scheduler&lt;span class=&quot;s1&quot;&gt;&apos;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;TimeoutSec=0
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, enable the service for auto start at boot and start it for the current session with:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;chmod 755 /etc/systemd/system/io-scheduler.service
systemctl enable io-scheduler.service
systemctl start io-scheduler.service
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Wed, 16 Jul 2014 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2014/07/16/changing-the-io-scheduler-on-a-specific-disk.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2014/07/16/changing-the-io-scheduler-on-a-specific-disk.html</guid>
        
        <category>Fedora</category>
        
        <category>I/O Scheduler</category>
        
        <category>Noop</category>
        
        <category>Queue</category>
        
        <category>Scheduler</category>
        
        <category>Systemd</category>
        
        
      </item>
    
      <item>
        <title>Videostream on Fedora 20</title>
        <description>&lt;p&gt;Videostream is the ultimate Chromecast app. Unfortunately, Chromecast and Videostream do not work out of the box on recent Fedora versions due to firewalld: some minor configuration is required. The configuration consists in opening port ranges &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;32768-61000&lt;/code&gt; (UDP) for Chromecast and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5550-5559&lt;/code&gt; (TCP) for Videostream.&lt;/p&gt;

&lt;p&gt;Below are the commands to enter in your terminal to complete the configuration in a few seconds:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;firewall-cmd --permanent --add-port=32768-61000/udp
firewall-cmd --permanent --add-port=5550-5559/tcp
firewall-cmd --reload
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 15 Jul 2014 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2014/07/15/videostream-on-fedora-20.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2014/07/15/videostream-on-fedora-20.html</guid>
        
        <category>Chromecast</category>
        
        <category>Fedora</category>
        
        <category>Firewalld</category>
        
        <category>Videostream</category>
        
        
      </item>
    
      <item>
        <title>Eclipse sysargs code templates</title>
        <description>&lt;p&gt;Eclipse provides many useful shortcuts including code templates such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysout&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syserr&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systrace&lt;/code&gt; that you can use with autocompletion (CTRL + Space). However, sometimes you may want to debug a method call without using the eclipse debugging machinery. In that case, you may have to print the value of received parameters. The following will explain how to configure a new Eclipse code template named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysargs&lt;/code&gt; that, once used with auto completion, inserts the piece of code required to print the method parameters where the shortcut was used.&lt;/p&gt;

&lt;!--more--&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sysargs&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Concretely, if your purpose is to debug the method above, what you will have to do is to write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysargs&lt;/code&gt; as depicted on line 2, then press CTRL+Space and you get &lt;em&gt;automagically&lt;/em&gt; the piece of code below that is ready to be executed for displaying parameter values.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;my.package.MyClass#method(arg1, arg2, arg3) = (&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The configuration is really simple. Go to &lt;em&gt;Preferences&lt;/em&gt;, &lt;em&gt;Java&lt;/em&gt;, &lt;em&gt;Editor&lt;/em&gt;, &lt;em&gt;Templates&lt;/em&gt;. Then, click on the &lt;em&gt;New&lt;/em&gt; button and enter the name &lt;em&gt;sysargs&lt;/em&gt; for your new code template. Finally, copy/paste the following piece of code as pattern.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;${enclosing_package}.${enclosing_type}#${enclosing_method}(${enclosing_method_arguments}) = (&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enclosing_method_arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s all, you are ready to use sysargs!&lt;/p&gt;
</description>
        <pubDate>Sat, 14 May 2011 00:00:00 +0000</pubDate>
        <link>https://pellegrino.link/2011/05/14/eclipse-sysargs-code-templates.html</link>
        <guid isPermaLink="true">https://pellegrino.link/2011/05/14/eclipse-sysargs-code-templates.html</guid>
        
        <category>Code template</category>
        
        <category>Eclipse</category>
        
        <category>Java</category>
        
        <category>Sysargs</category>
        
        
      </item>
    
  </channel>
</rss>
