<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8668853818783919860</id><updated>2012-02-16T14:44:04.528-08:00</updated><category term='bugparade'/><title type='text'>CALL GLOP()</title><subtitle type='html'>Andy Malakov software blog</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andy-malakov.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>29</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-8508850832349554466</id><published>2011-12-05T17:44:00.000-08:00</published><updated>2011-12-05T17:45:50.883-08:00</updated><title type='text'>My CPU collection</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-XUvfZbupHxw/Tt1zsDAAA9I/AAAAAAAAGhQ/uU36dbRXAtU/s1600/IMG_1386.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 287px;" src="http://4.bp.blogspot.com/-XUvfZbupHxw/Tt1zsDAAA9I/AAAAAAAAGhQ/uU36dbRXAtU/s400/IMG_1386.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5682825505368179666" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-8508850832349554466?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8508850832349554466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8508850832349554466'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2011/12/my-cpu-collection.html' title='My CPU collection'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-XUvfZbupHxw/Tt1zsDAAA9I/AAAAAAAAGhQ/uU36dbRXAtU/s72-c/IMG_1386.JPG' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-2550710937236256165</id><published>2010-10-11T14:50:00.000-07:00</published><updated>2010-10-11T14:51:12.014-07:00</updated><title type='text'>ShouldNotReachHere</title><content type='html'>#&lt;br /&gt;# A fatal error has been detected by the Java Runtime Environment:&lt;br /&gt;#&lt;br /&gt;#  Internal Error (classFileParser.cpp:3161), pid=3136, tid=4676&lt;br /&gt;#  Error: ShouldNotReachHere()&lt;br /&gt;#&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-2550710937236256165?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/2550710937236256165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/2550710937236256165'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2010/10/shouldnotreachhere.html' title='ShouldNotReachHere'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-274979453390817012</id><published>2010-10-03T22:17:00.000-07:00</published><updated>2010-10-10T21:26:15.595-07:00</updated><title type='text'>My first Android app</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qOaAwvezbUk/TLKRx-KteAI/AAAAAAAAFfc/d6had45OXT0/s1600/MayaCalendar.jpg"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 276px; height: 320px;" src="http://1.bp.blogspot.com/_qOaAwvezbUk/TLKRx-KteAI/AAAAAAAAFfc/d6had45OXT0/s320/MayaCalendar.jpg" alt="" id="BLOGGER_PHOTO_ID_5526639980424558594" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qOaAwvezbUk/TKljrgDFSDI/AAAAAAAAFfU/tnGIulslNGQ/s1600/maya-calendar-b1.jpg"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I created my first Android app. It converts a date in Gregorian Calendar into Maya "Long Count" calendar. Contrary to popular view Mayan calendar doesn't end on December 21st, 2012. You can test this in my app :-).&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Sources can be found &lt;a href="http://code.google.com/p/maya-calendar-android/"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-274979453390817012?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/274979453390817012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/274979453390817012'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2010/10/my-first-android-app.html' title='My first Android app'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_qOaAwvezbUk/TLKRx-KteAI/AAAAAAAAFfc/d6had45OXT0/s72-c/MayaCalendar.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-8421689436875840647</id><published>2010-06-06T19:12:00.000-07:00</published><updated>2010-06-07T13:57:57.212-07:00</updated><title type='text'>Alternative to Thread.sleep()</title><content type='html'>Follow-up to my &lt;a href="http://andy-malakov.blogspot.com/2010/05/measuring-nanoseconds-in-java-windows.html"&gt;previous post&lt;/a&gt;. Here is an alternative to Thread.sleep() that uses spin-yield:&lt;br /&gt;&lt;pre&gt;&lt;span class="s0"&gt;&lt;a name="l11"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l12"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l12"&gt;private static final long &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l12"&gt;SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(&lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l12"&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l12"&gt;);  &lt;/a&gt;&lt;/span&gt;&lt;span class="s3"&gt;&lt;a name="l12"&gt;//TODO: Determine for current machine&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l12"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l13"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l14"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;public static void &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l14"&gt;sleepNanos (&lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;long &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l14"&gt;nanoDuration) &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;throws &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l14"&gt;InterruptedException {&lt;br /&gt;&lt;/a&gt;&lt;a name="l15"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l15"&gt;final long &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l15"&gt;end = System.nanoTime() + nanoDuration;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l16"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l17"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l17"&gt;long &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l17"&gt;timeLeft = nanoDuration;&lt;br /&gt;&lt;/a&gt;&lt;a name="l18"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l18"&gt;do &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l18"&gt;{&lt;br /&gt;&lt;/a&gt;&lt;a name="l19"&gt;            &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l19"&gt;if &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l19"&gt;(timeLeft &amp;gt; SLEEP_PRECISION)&lt;br /&gt;&lt;/a&gt;&lt;a name="l20"&gt;                Thread.sleep (&lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l20"&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l20"&gt;);&lt;br /&gt;&lt;/a&gt;&lt;a name="l21"&gt;            &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l21"&gt;else&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l21"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l22"&gt;                Thread.sleep (&lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l22"&gt;0&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l22"&gt;); &lt;/a&gt;&lt;/span&gt;&lt;span class="s3"&gt;&lt;a name="l22"&gt;// Thread.yield();&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l22"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l23"&gt;            timeLeft = end - System.nanoTime();&lt;br /&gt;&lt;/a&gt;&lt;a name="l24"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l25"&gt;            &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l25"&gt;if &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l25"&gt;(Thread.interrupted())&lt;br /&gt;&lt;/a&gt;&lt;a name="l26"&gt;                &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l26"&gt;throw new &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l26"&gt;InterruptedException ();&lt;br /&gt;&lt;/a&gt;&lt;a name="l27"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l28"&gt;        } &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l28"&gt;while &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l28"&gt;(timeLeft &amp;gt; &lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l28"&gt;0&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l28"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l29"&gt;    }&lt;/a&gt;&lt;/span&gt;&lt;/pre&gt;&lt;a name="l29"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Test&lt;/h2&gt;&lt;br /&gt;I run 4 threads requesting 5 millisecond sleep 1000 times each (on my Dual-Core CPU). The first chart shows &lt;tt&gt;sleepNanos(TimeUnit.MILLISECONDS(5).toNanos())&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:left;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_qOaAwvezbUk/TAxhWXXhgjI/AAAAAAAAFQw/HxcOSfEC9l4/s1600/SleepStatsNanos.jpg" border="0" alt="Actual sleep time of sleepNanos(5000000)"/&gt;&lt;br /&gt;&lt;br /&gt;The second chart shows &lt;tt&gt;Thread.sleep(5)&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:left;cursor:pointer; cursor:hand" src="http://4.bp.blogspot.com/_qOaAwvezbUk/TAxhiYN0lNI/AAAAAAAAFQ4/QwqasE0C5u0/s1600/SleepStatsStd.jpg" border="0" alt="Actual sleep time of Thread.sleep(5)" /&gt;&lt;br /&gt;&lt;br /&gt;As you can see, sleepNanos() is much more precise. I found that this approach was originally used by &lt;a href="http://www.geisswerks.com/ryan/FAQS/timing.html"&gt;Ryan Geiss for WinAmp visualization plugin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;UPDATE&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Even better precision can be achieved if you are willing to consume more CPU power doing Spin-Wait for the last part of the wait:&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:left;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_qOaAwvezbUk/TA1bSCHh8cI/AAAAAAAAFRA/9wmP5VX9I1U/s1600/sleepSpinNanos.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5480136686943990210" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="s0"&gt; &lt;br /&gt;&lt;a name="l14"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l15"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;public static void &lt;/span&gt;&lt;span class="s0"&gt;sleepNanos (&lt;/span&gt;&lt;span class="s1"&gt;long &lt;/span&gt;&lt;span class="s0"&gt;nanoDuration) &lt;/span&gt;&lt;span class="s1"&gt;throws &lt;/span&gt;&lt;span class="s0"&gt;InterruptedException { &lt;br /&gt;&lt;/a&gt;&lt;a name="l16"&gt;        &lt;/span&gt;&lt;span class="s1"&gt;final long &lt;/span&gt;&lt;span class="s0"&gt;end = System.nanoTime() + nanoDuration; &lt;br /&gt;&lt;/a&gt;&lt;a name="l17"&gt;        &lt;/span&gt;&lt;span class="s1"&gt;long &lt;/span&gt;&lt;span class="s0"&gt;timeLeft = nanoDuration; &lt;br /&gt;&lt;/a&gt;&lt;a name="l18"&gt;        &lt;/span&gt;&lt;span class="s1"&gt;do &lt;/span&gt;&lt;span class="s0"&gt;{ &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l19"&gt;            &lt;/span&gt;&lt;span class="s1"&gt;if &lt;/span&gt;&lt;span class="s0"&gt;(timeLeft &amp;gt; SLEEP_PRECISION) &lt;br /&gt;&lt;/a&gt;&lt;a name="l20"&gt;                Thread.sleep (&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="s0"&gt;); &lt;br /&gt;&lt;/a&gt;&lt;a name="l21"&gt;            &lt;/span&gt;&lt;span class="s1"&gt;else&lt;/span&gt;&lt;span class="s0"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l22"&gt;                &lt;/span&gt;&lt;span class="s1"&gt;if &lt;/span&gt;&lt;span class="s0"&gt;(timeLeft &amp;gt; SPIN_YIELD_PRECISION) &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l23"&gt;                    Thread.sleep(&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="s0"&gt;); &lt;br /&gt;&lt;/a&gt;&lt;a name="l24"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l25"&gt;            timeLeft = end - System.nanoTime(); &lt;br /&gt;&lt;/a&gt;&lt;a name="l26"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l27"&gt;            &lt;/span&gt;&lt;span class="s1"&gt;if &lt;/span&gt;&lt;span class="s0"&gt;(Thread.interrupted()) &lt;br /&gt;&lt;/a&gt;&lt;a name="l28"&gt;                &lt;/span&gt;&lt;span class="s1"&gt;throw new &lt;/span&gt;&lt;span class="s0"&gt;InterruptedException (); &lt;br /&gt;&lt;/a&gt;&lt;a name="l29"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l30"&gt;        } &lt;/span&gt;&lt;span class="s1"&gt;while &lt;/span&gt;&lt;span class="s0"&gt;(timeLeft &amp;gt; &lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="s0"&gt;); &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l31"&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-8421689436875840647?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8421689436875840647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8421689436875840647'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2010/06/alternative-to-threadsleep.html' title='Alternative to Thread.sleep()'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_qOaAwvezbUk/TAxhWXXhgjI/AAAAAAAAFQw/HxcOSfEC9l4/s72-c/SleepStatsNanos.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-3445214118095688427</id><published>2010-05-13T10:35:00.001-07:00</published><updated>2010-05-17T19:42:27.051-07:00</updated><title type='text'>Measuring nanoseconds in Java / Windows</title><content type='html'>&lt;p&gt;I was under false impression that interval timers in Java allow sub-millisecond precision on Windows. I knew that Thread.sleep(millis, nanos) internally uses milliseconds, but for some reason I thought that methods like &lt;tt&gt;LockSupport.parkNanos()&lt;/tt&gt; method provide precise waits. Well, I was wrong. The smallest delay this method can realize is approximately 1.95 milliseconds on my Windows PC.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Back in 2006 David Holmes &lt;a href="http://blogs.sun.com/dholmes/entry/inside_the_hotspot_vm_clocks"&gt;explained&lt;/a&gt; that Java timer intervals are based on &lt;tt&gt;waitForMultipleObjects()&lt;/tt&gt; Windows API (which uses dwMilliseconds). They still are.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;One simple (but not universal) workaround is a "spin-sleep":&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    private static void sleepNanos (long nanoDelay) {&lt;br /&gt;        final long end = System.nanoTime() + nanoDelay;&lt;br /&gt;        do {&lt;br /&gt;            Thread.yield();  // Thread.sleep (0);&lt;br /&gt;        } while (System.nanoTime() &lt; end);&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When running standalone this method consumes all free resources of single CPU core, but it will share with other threads that may be running. For large durations it can be enhanced to use Thread.sleep() for bulk of the waiting.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;P.S. Difference between Thread.yield() and Thread.sleep( 0 ) is explained &lt;a href='http://www.javamex.com/tutorials/threads/yield.shtml'&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-3445214118095688427?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3445214118095688427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3445214118095688427'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2010/05/measuring-nanoseconds-in-java-windows.html' title='Measuring nanoseconds in Java / Windows'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-6255863024476265364</id><published>2009-12-11T14:40:00.000-08:00</published><updated>2009-12-11T15:03:04.150-08:00</updated><title type='text'>Old trap</title><content type='html'>I was puzzled why one of my objects had incorrect toString()&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="s0"&gt;class &lt;/span&gt;&lt;span class="s1"&gt;Foo { &lt;br /&gt;&lt;a name="l5"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l5"&gt;private long &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l5"&gt;id; &lt;br /&gt;&lt;/a&gt;&lt;a name="l6"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l6"&gt;private &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l6"&gt;String name; &lt;br /&gt;&lt;/a&gt;&lt;a name="l7"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l8"&gt;    Foo(&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l8"&gt;long &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l8"&gt;id, String name) { &lt;br /&gt;&lt;/a&gt;&lt;a name="l9"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l9"&gt;this&lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l9"&gt;.id = id; &lt;br /&gt;&lt;/a&gt;&lt;a name="l10"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l10"&gt;this&lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l10"&gt;.name = name; &lt;br /&gt;&lt;/a&gt;&lt;a name="l11"&gt;    } &lt;br /&gt;&lt;/a&gt;&lt;a name="l12"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l13"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l13"&gt;public &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l13"&gt;String toString () { &lt;br /&gt;&lt;/a&gt;&lt;a name="l14"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l14"&gt;return &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;id + &lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l14"&gt;' ' &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;+ name; &lt;br /&gt;&lt;/a&gt;&lt;a name="l15"&gt;    } &lt;br /&gt;&lt;/a&gt;&lt;a name="l16"&gt;}&lt;/a&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The statement &lt;tt&gt;new Foo(123, "Hello")&lt;/tt&gt; prints something like "155Hello" instead of "123 Hello". Of course the reason is pretty simple:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="s0"&gt; &lt;br /&gt;&lt;a name="l18"&gt; &lt;/a&gt;&lt;a name="l19"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l19"&gt;public &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l19"&gt;String toString2() { &lt;br /&gt;&lt;/a&gt;&lt;a name="l20"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l20"&gt;return new &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l20"&gt;StringBuilder().append(id + &lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l20"&gt;32L&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l20"&gt;).append(name.toString()).toString(); &lt;br /&gt;&lt;/a&gt;&lt;a name="l21"&gt;    }&lt;/a&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-6255863024476265364?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/6255863024476265364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/6255863024476265364'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/12/old-trap.html' title='Old trap'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-8904018503953454461</id><published>2009-11-11T08:45:00.000-08:00</published><updated>2009-11-11T16:23:30.996-08:00</updated><title type='text'>Stack allocation in Java is still a myth</title><content type='html'>&lt;p&gt;There were rumors that Mustang will have &lt;a href='http://www.ibm.com/developerworks/java/library/j-jtp09275.html'&gt;on stack allocation&lt;/a&gt; as a part of hot spot optimization.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Four+ years later this :&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; encode (String input) {&lt;br /&gt;   final &lt;span class="kwrd"&gt;byte&lt;/span&gt; [] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt; [8];  &lt;br /&gt;&lt;br /&gt;   .. encode input into buffer &lt;br /&gt;&lt;br /&gt;   .. convert buffer into LONG &lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I was hoping JVM will allocate &lt;tt&gt;buffer&lt;/tt&gt; on stack based on the fact that it does not escape from this method. Running this test 10M times with &lt;tt&gt;-verbosegc&lt;/tt&gt; shows extensive GC work (1.6.0_16-b01 64 bit server JVM with  -XX:+DoEscapeAnalysis option).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;On the positive side. GC is very fast. Consider three functions:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;encodeNewBuffer () uses new byte array to encode input string. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;encodeSynchronizedField () uses private field, guarded by synchronized{} block&lt;/li&gt;&lt;br /&gt;&lt;li&gt;encodeThreadLocalField () uses ThreadLocal cache to encode input string&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Here is the code:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;long&lt;/span&gt; encodeNewBuffer (String input) {&lt;br /&gt;   final &lt;span class="kwrd"&gt;byte&lt;/span&gt; [] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt; [8];  &lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;return&lt;/span&gt; f (buffer);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/////////////&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; final &lt;span class="kwrd"&gt;byte&lt;/span&gt; [] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt; [8];  &lt;br /&gt;&lt;br /&gt;synchronized &lt;span class="kwrd"&gt;long&lt;/span&gt; encodeSynchronizedField (String input) {&lt;br /&gt;   &lt;span class="kwrd"&gt;return&lt;/span&gt; f (buffer);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/////////////&lt;br /&gt;&lt;br /&gt;ThreadLocal&amp;lt;&lt;span class="kwrd"&gt;byte&lt;/span&gt;[]&amp;gt; threadLocal = &lt;span class="kwrd"&gt;new&lt;/span&gt; ThreadLocal&amp;lt;&lt;span class="kwrd"&gt;byte&lt;/span&gt;[]&amp;gt;();&lt;br /&gt;{&lt;br /&gt;    threadLocal.set(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt; [8]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;long&lt;/span&gt; encodeThreadLocalField (String input) {&lt;br /&gt;   &lt;span class="kwrd"&gt;byte&lt;/span&gt; [] buffer = threadLocal.get();&lt;br /&gt;   &lt;span class="kwrd"&gt;return&lt;/span&gt; f (buffer);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;GC-based method is a winner:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;encodeNewBuffer():         4,108 sec. &lt;br /&gt;encodeSynchronizedField(): 5,322 sec.&lt;br /&gt;encodeThreadLocalField() : 5,411 sec&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-8904018503953454461?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8904018503953454461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8904018503953454461'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/11/stack-allocation-in-java-is-still-myth.html' title='Stack allocation in Java is still a myth'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-6016015377990387731</id><published>2009-11-09T09:38:00.001-08:00</published><updated>2009-11-11T10:19:44.323-08:00</updated><title type='text'>Multi-threaded testing with JUnit. Switch to ConcJUnit .</title><content type='html'>Our JUnit tests deal with components that use multiple threads. Unfortunately JUnit has no built-in support for this kind of testing. &lt;br /&gt;&lt;br /&gt;Lets consider a simple thread that interprets commands from input queue. In this example it can only understand "exit" command. All other inputs trigger an error.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="s0"&gt; &lt;br /&gt;&lt;a name="l8"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l9"&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l9"&gt;abstract class &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l9"&gt;MainLoop &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l9"&gt;extends &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l9"&gt;Thread { &lt;br /&gt;&lt;/a&gt;&lt;a name="l10"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l11"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l11"&gt;private &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l11"&gt;Queue&amp;lt;String&amp;gt; commands = &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l11"&gt;new &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l11"&gt;LinkedBlockingDeque&amp;lt;String&amp;gt;(); &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l12"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l13"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l13"&gt;public void &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l13"&gt;run () { &lt;br /&gt;&lt;/a&gt;&lt;a name="l14"&gt;        &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;while &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l14"&gt;(&lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l14"&gt;true&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l14"&gt;) { &lt;br /&gt;&lt;/a&gt;&lt;a name="l15"&gt;            String command = commands.poll(); &lt;br /&gt;&lt;/a&gt;&lt;a name="l16"&gt;            &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l16"&gt;if &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l16"&gt;(command.equals (&lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l16"&gt;"exit"&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l16"&gt;)) &lt;br /&gt;&lt;/a&gt;&lt;a name="l17"&gt;                &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l17"&gt;break&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l17"&gt;; &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l18"&gt;            &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l18"&gt;else&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l18"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l19"&gt;                reportError (&lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l19"&gt;"Unknown command: " &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l19"&gt;+ command); &lt;br /&gt;&lt;/a&gt;&lt;a name="l20"&gt;        } &lt;br /&gt;&lt;/a&gt;&lt;a name="l21"&gt;    } &lt;br /&gt;&lt;/a&gt;&lt;a name="l22"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l23"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l23"&gt;public void &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l23"&gt;add (String command) { &lt;br /&gt;&lt;/a&gt;&lt;a name="l24"&gt;        commands.add(command); &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l25"&gt;    } &lt;br /&gt;&lt;/a&gt;&lt;a name="l26"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l27"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l27"&gt;abstract void &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l27"&gt;reportError (String error); &lt;br /&gt;&lt;/a&gt;&lt;a name="l28"&gt;} &lt;br /&gt;&lt;/a&gt;&lt;a name="l29"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l30"&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l30"&gt;public class &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l30"&gt;MyTest { &lt;br /&gt;&lt;/a&gt;&lt;a name="l31"&gt; &lt;br /&gt;&lt;/a&gt;&lt;a name="l32"&gt;    @Test &lt;br /&gt;&lt;/a&gt;&lt;a name="l33"&gt;    &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l33"&gt;public void &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l33"&gt;test() { &lt;br /&gt;&lt;/a&gt;&lt;a name="l34"&gt;        MainLoop thread = &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l34"&gt;new &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l34"&gt;MainLoop() { &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l35"&gt;            &lt;/a&gt;&lt;/span&gt;&lt;span class="s1"&gt;&lt;a name="l35"&gt;void &lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l35"&gt;reportError(String error) { &lt;br /&gt;&lt;/a&gt;&lt;a name="l36"&gt;                Assert.fail (error); &lt;br /&gt;&lt;/a&gt;&lt;a name="l37"&gt;            } &lt;br /&gt;&lt;/a&gt;&lt;a name="l38"&gt;        }; &lt;br /&gt;&lt;/a&gt;&lt;a name="l39"&gt;        thread.start(); &lt;br /&gt;&lt;/a&gt;&lt;a name="l40"&gt;        thread.add (&lt;/a&gt;&lt;/span&gt;&lt;span class="s2"&gt;&lt;a name="l40"&gt;"quit"&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l40"&gt;); &lt;/a&gt;&lt;/span&gt;&lt;span class="s3"&gt;&lt;a name="l40"&gt;// sic! shoudl be "exit"&lt;/a&gt;&lt;/span&gt;&lt;span class="s0"&gt;&lt;a name="l40"&gt; &lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a name="l41"&gt;    } &lt;br /&gt;&lt;/a&gt;&lt;a name="l42"&gt;} &lt;br /&gt;&lt;/a&gt;&lt;a name="l43"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If we run the above test, JUnit completely ignores failure of "Commands Interpreter" thread (Although default uncaughtExceptionHandler prints exception to standard output):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   [junit] Running test.MyTest&lt;br /&gt;   [junit] Exception in thread "Commands Interpreter": java.lang.AssertionError: Unknown command: quit&lt;br /&gt;   [junit]      at org.junit.Assert.fail(Assert.java:91)&lt;br /&gt;   [junit]      at test.MyTest$1.reportError(MyTest.java:36)&lt;br /&gt;   [junit]      at test.MainLoop.run(MyTest.java:19)&lt;br /&gt;   [junit] Tests run: 1, &lt;b&gt;Failures: 0, Errors: 0&lt;/b&gt;, Time elapsed: 0.422 sec&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see JUnit detected 0 errors. JUnit has at least two problems when it comes to multi-threaded tests:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;JUnit only cares about errors in its own thread. It completely ignores exceptions or assertion failures in child threads. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Left over child threads may produce side effect on subsequent tests. In some cases failures in child threads may happen after the main thread is finished.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;We used various custom workarounds until it was clear that we need a generic solution for growing number of multi-threaded tests. Luckily we found an excellent tool - &lt;a href='http://www.cs.rice.edu/~mgricken/research/concutest/concjunit/'&gt;ConcJUnit&lt;/a&gt;  (AKA ConcuTest) written by Mathias Ricken.&lt;br /&gt;&lt;br /&gt;a) ConcJUnit is a drop-in replacement of JUnit. It includes standard JUnit classes and introduces own test runners. Just replace junit.jar by concutest.jar .&lt;br /&gt;&lt;br /&gt;b) ConcJUnit detects both failures in child threads and leftover threads.&lt;br /&gt;&lt;br /&gt;Switching to ConcJUnit produces expected result:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;java.lang.AssertionError: Unknown command: quit&lt;br /&gt; at org.junit.Assert.fail(Assert.java:91)&lt;br /&gt; at test.MyTest$1.reportError(MyTest.java:36)&lt;br /&gt; at test.MainLoop.run(MyTest.java:19)&lt;br /&gt; at test.MainLoop.run(MyTest.java:19)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you want to know more about ConcJUnit, read materials from &lt;a href='http://www.cs.rice.edu/~mgricken/research/concutest/intro.shtml'&gt;introduction&lt;/a&gt; page. For example, the following &lt;a href='http://www.cs.rice.edu/~mgricken/research/concutest/download/PPPJ2009-Ricken-ConcJUnit-2009-08-28.ppt'&gt;presentation&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-6016015377990387731?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/6016015377990387731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/6016015377990387731'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/11/multi-threaded-testing-with-junit.html' title='Multi-threaded testing with JUnit. Switch to ConcJUnit .'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-3528456948571841451</id><published>2009-11-05T08:38:00.000-08:00</published><updated>2009-11-05T08:48:06.031-08:00</updated><title type='text'>GLOP</title><content type='html'>"Consider a program — any program; let us call it GLOP. We begin designing our program by imagining that we have a machine with a hardware instruction that will perform GLOP (an idea that is not beyond the realm of possibility with today's microprogrammable computers) Thus, to write program GLOP, we merely write the instruction &lt;pre&gt;GLOP&lt;/pre&gt; and we are done! Not only are we finished, but we are relatively certain that the resulting program is correct — assuming that the hardware primitive GLOP performs correctly (and if it doesn't, we can always blame it on the vendor)."&lt;br /&gt;&lt;br /&gt;Edward Yourdon "Techniques of program structure and design‎" 1975.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-3528456948571841451?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3528456948571841451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3528456948571841451'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/11/glop.html' title='GLOP'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-7884148101808295142</id><published>2009-11-03T16:59:00.001-08:00</published><updated>2009-11-03T16:59:55.390-08:00</updated><title type='text'></title><content type='html'>2:5020/236.23 :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-7884148101808295142?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/7884148101808295142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/7884148101808295142'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/11/25020236.html' title=''/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-3581348110243928801</id><published>2009-10-08T21:27:00.001-07:00</published><updated>2009-10-09T11:08:53.030-07:00</updated><title type='text'>sizeof and object padding in Java</title><content type='html'>Consider the following classes:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct1 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct2 extends Struct1 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b2;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct3 extends Struct2 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b3;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct4 extends Struct3 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b4;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct5 extends Struct4 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b5;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct6 extends Struct5 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b6;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct7 extends Struct6 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b7;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Struct8 extends Struct7 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b8;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; FlatStruct8 {&lt;br /&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt; b1, b2, b3, b4, b5, b6, b7, b8;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On my JVM (1.6.0_16 64-bit):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sizeof (new Struct8()) = 80 (sic!)&lt;br /&gt;sizeof (new FlatStruct8()) = 24&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, 24 makes sense (8 bytes of data + 2 x 8 bytes of object overhead). In case of Struct8, we can see that Java pads fields declared in each class to so that total block size will be multiple of 8.&lt;br /&gt;&lt;br /&gt;I used both &lt;a href='http://sizeof.sourceforge.net/'&gt;Instrumentation-based &lt;/a&gt; and &lt;a href='http://jroller.com/mipsJava/entry/sizeof_java_objects'&gt;GC-based&lt;/a&gt; sizeof () implementations to confirm this. &lt;br /&gt;&lt;br /&gt;On 32-bit JVM (1.6.0_04-b12) blocks are padded to multiple of 4.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sizeof (new Struct8()) = 40 &lt;br /&gt;sizeof (new FlatStruct8()) = 24&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.javamex.com/tutorials/memory/object_memory_usage.shtml'&gt;More&lt;/a&gt; about padding.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-3581348110243928801?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3581348110243928801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3581348110243928801'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/10/object-alignment-in-java.html' title='sizeof and object padding in Java'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-733049910687591776</id><published>2009-07-27T15:16:00.000-07:00</published><updated>2009-07-27T15:35:13.672-07:00</updated><title type='text'>Faster JUL logging</title><content type='html'>Here are the steps we followed to improve java.util.logging performance:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Switched from SimpleFormatter to our custom formatter. It boosted performance up to 6 times. Our formatter prints only time-of-day portion of timestamp (using custom formatting function). Our log files also omit class/method/thread context for each log message. It also uses custom MessageFormatter (based on StringBuilder).&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Tweaked FileHandler to flush every 8K rather than after each message. This boosts performance up to 2.5 times.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;We tried using Java7 logger package. We didn't notice considerable improvements for our usage patterns.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Credit for much of this work goes to my colleague Nikolay Dul.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-733049910687591776?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/733049910687591776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/733049910687591776'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/07/follow-up-to-logging.html' title='Faster JUL logging'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-4895078479042947372</id><published>2009-07-22T18:37:00.000-07:00</published><updated>2009-07-27T15:16:06.732-07:00</updated><title type='text'>Java logging</title><content type='html'>Am I the only one who misses&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void log (Level level, String msg, Object ... params)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Instead of existing&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void log (Level level, String msg, Object [] params)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;in java.util.logging.Logger ?&lt;br /&gt;&lt;br /&gt;P.S. Apparently not: enhancement request was filed back in &lt;a href='http://bugs.sun.com/view_bug.do?bug_id=6540440'&gt;2004&lt;/a&gt;. I will see what I can do...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-4895078479042947372?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/4895078479042947372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/4895078479042947372'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/07/java-logging.html' title='Java logging'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-1125702272787398622</id><published>2009-06-13T18:16:00.000-07:00</published><updated>2009-06-16T10:48:44.144-07:00</updated><title type='text'>Writing game bot in Java</title><content type='html'>Can Java be used to write a simple MMORPG &lt;a href="http://en.wikipedia.org/wiki/Computer_game_bot"&gt;game bots&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;Easily. Java has a class &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Robot.html"&gt;java.awt.Robot&lt;/a&gt; that is intended for writing automated tests and provides just what we need.&lt;br /&gt;&lt;br /&gt;First, lets create a bot that will keep an eye on your character's health status.  The basic idea is very simple - when health status is running low, drink a healing potion. Repeat. This simple script covers your back and releases your mind from some routine actions. You will concentrate on attacking your opponent ;-)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;import java.awt.Color;&lt;br /&gt;import java.awt.Robot;&lt;br /&gt;import java.awt.Toolkit;&lt;br /&gt;import static java.awt.event.KeyEvent.*;&lt;br /&gt;&lt;br /&gt;private Toolkit toolkit = Toolkit.getDefaultToolkit();&lt;br /&gt;private Robot robot = new Robot();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We need two type of things:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Inspect some area of the screen that shows your character health's status (usually appears as some sort of progress bar). We just need to know when some pixel inside the bar is getting black:&lt;br /&gt;&lt;pre&gt;boolean isBlack (int x, int y) {&lt;br /&gt;  Color c = robot.getPixelColor (x, y);&lt;br /&gt;  return c.getRed() &lt; 16 &amp;&amp; c.getGreen() &lt; 16 &amp;&amp; c.getBlue() &lt; 16;&lt;br /&gt;}&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Simulating keyboard action is also easy (we need to press a hotkey for your healing potions)&lt;br /&gt;&lt;pre&gt;void key (int keyCode, long duration) throws InterruptedException {&lt;br /&gt;  robot.keyPress(keyCode);&lt;br /&gt;  Thread.sleep(duration);&lt;br /&gt;  robot.keyRelease(keyCode);&lt;br /&gt;}&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Now the program itself is trivial:&lt;br /&gt;&lt;pre&gt;while (true) {&lt;br /&gt;    if (isBlack (90, 760)) &lt;br /&gt;      key (VK_F1, 500);&lt;br /&gt;    &lt;br /&gt;    Thread.sleep (50);   &lt;br /&gt;  }  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here I assume that your healing potions are assigned to hotkey F1 (KeyEvent.VK_F1) and coordinates {90, 760} show your health status and become black when health is below 25% (your can use Paint or some other program to analyze game's screen shot). &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Similar approach can be used to automate other tedious MMORPG tasks (mining gold, fishing, or gaining experience). &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;P.S. Take a look at this guy's &lt;a href="http://www.picamatic.com/view/1894033_1227048032450/"&gt;screen&lt;/a&gt; (like a Boeing cockpit).&lt;br /&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;DISCLAIMER:Check your game's license before using this technique. It may be prohibited as something that gives unfair advantage over other players.&lt;br /&gt;&lt;hr/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-1125702272787398622?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/1125702272787398622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/1125702272787398622'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2009/06/writing-game-bot-in-java.html' title='Writing game bot in Java'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-3071051828899796300</id><published>2008-12-24T18:31:00.000-08:00</published><updated>2009-02-28T13:24:13.063-08:00</updated><title type='text'>My favorite features in Scala</title><content type='html'>&lt;ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt; Tupples in function results&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def f(a: int, b: int) : (int, int) = (a/b, a%b)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt; type &lt;tt&gt;Nothing&lt;/tt&gt; and &lt;tt&gt;Null&lt;/tt&gt; (like NONE and ANY in Eiffel)&lt;br /&gt;&lt;li&gt;Object definitions&lt;br /&gt;&lt;pre&gt;object Singleton { }&lt;/pre&gt;&lt;br /&gt;&lt;li&gt;Parameterless methods, that can be overridden by fields and vice versa. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Circle(radius:double) {&lt;br /&gt;  def diameter = 2*radius&lt;br /&gt;}&lt;br /&gt;...&lt;br /&gt;new Circle(5).diameter&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Subtyping of generics (so-called co-variant subtyping). I miss this feature in Java:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def Iterator[+E] ...&lt;br /&gt;now Iterator[String] will assign to Iterator[AnyObj].&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Pattern-matching expressions? Need to try it.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Some of these I was missing since I programmed in Eiffel back in 1995.&lt;br /&gt;&lt;br /&gt;Features I am not so fond of:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Case classes (a-la subtyped enums?)&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-3071051828899796300?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3071051828899796300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3071051828899796300'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/12/my-favorite-features-in-scala.html' title='My favorite features in Scala'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-5879303130863268261</id><published>2008-09-30T20:13:00.000-07:00</published><updated>2010-07-08T12:28:33.951-07:00</updated><title type='text'>Mindstorms are back</title><content type='html'>Online game like this will be excellent for software job interview. &lt;br /&gt;&lt;div style="width: 148px; border: 1px solid #BBB; padding: 5px;background-color: white;"&gt;&lt;a href="http://armorgames.com/play/2205/light-bot"&gt;&lt;img alt="Cover voor Light Bot" src="http://www.gameroo.nl/covers/0000/0456/light-bot_medium.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-5879303130863268261?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5879303130863268261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5879303130863268261'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/09/mindstorms-are-back.html' title='Mindstorms are back'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-3709801344237280012</id><published>2008-09-12T07:29:00.000-07:00</published><updated>2008-09-12T08:13:48.549-07:00</updated><title type='text'>Obfuscated code</title><content type='html'>Situation: Third-party client API library periodically fails with nasty exception:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Caused by: cli.System.AccessViolationException: Attempted to read or write protected memory.&lt;br /&gt;This is often an indication that other memory is corrupt.&lt;br /&gt;        at cli.TalTrade.Toolkit.DataBlock.ReadData(Unknown Source)&lt;br /&gt;        at cli.TalTrade.Toolkit.RawData.GetDataAsBlock(Unknown Source)&lt;br /&gt;        ... 34 more&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After verifying that input parameters are legitimate I decided to take a look at the failing code. My trusty Reflector exposed the following:&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;unsafe&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ReadData(&lt;span class="kwrd"&gt;void&lt;/span&gt; modopt(IsConstModifier)* pData)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;// This item is obfuscated and can not be translated.&lt;/span&gt;&lt;br /&gt;    ...&lt;br /&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (*(((&lt;span class="kwrd"&gt;int&lt;/span&gt;*) (&amp;amp;gtal_handle + 4)))[4] &amp;lt; 6)&lt;br /&gt;            &lt;span class="kwrd"&gt;goto&lt;/span&gt; Label_0038;&lt;br /&gt;    &lt;span class="kwrd"&gt;ushort&lt;/span&gt; num5 = *((&lt;span class="kwrd"&gt;ushort&lt;/span&gt;*) (((*(((&lt;span class="kwrd"&gt;int&lt;/span&gt;*) (&amp;amp;gtal_handle + 4))) + *(((&lt;span class="kwrd"&gt;int&lt;/span&gt;*) (&amp;amp;gtal_handle + 4)))[6]) - 8) + 6));&lt;br /&gt;    ... 100 more lines like these ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That code is supposed to read data block from memory queue and possibly format it as string.  What kind of secret know-how can it be?&lt;br /&gt;&lt;br /&gt;Now instead of figuring out the problem by ourselves we are going to send this error to the vendor. What a waste of time on both sides.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-3709801344237280012?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3709801344237280012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3709801344237280012'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/09/obfuscated-code.html' title='Obfuscated code'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-7257039330029758706</id><published>2008-08-14T06:54:00.000-07:00</published><updated>2008-08-14T06:58:12.578-07:00</updated><title type='text'>Motorola RAZR repair</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qOaAwvezbUk/SKQ5Vq5HYLI/AAAAAAAAB8s/iQCHbpLW8xc/s1600-h/IMG_5743.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_qOaAwvezbUk/SKQ5Vq5HYLI/AAAAAAAAB8s/iQCHbpLW8xc/s200/IMG_5743.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5234371711365243058" /&gt;&lt;/a&gt;Replaced keyboard in my cell phone. This is how it looked like at the worst moment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-7257039330029758706?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/7257039330029758706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/7257039330029758706'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/08/motorola-razr-repair.html' title='Motorola RAZR repair'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qOaAwvezbUk/SKQ5Vq5HYLI/AAAAAAAAB8s/iQCHbpLW8xc/s72-c/IMG_5743.JPG' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-5385513620867522255</id><published>2008-08-05T20:04:00.000-07:00</published><updated>2008-08-06T08:31:37.972-07:00</updated><title type='text'>Update on "direct vs. encapsulated field access times"</title><content type='html'>Update to &lt;a href="http://andy-malakov.blogspot.com/2008/08/direct-field-vs-method-access-times.html"&gt;earlier post&lt;/a&gt; about performance of direct field versus method-encapsulated access. A friend of mine pointed to strange decrease in method access performance right before it is getting compiled to native code. So I went back and I enhanced output of the benchmark:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; benchmark () throws Exception {&lt;br /&gt;       FieldAccessor fv = &lt;span class="kwrd"&gt;new&lt;/span&gt; FieldAccessor ();&lt;br /&gt;       MethodAssessor mv = &lt;span class="kwrd"&gt;new&lt;/span&gt; MethodAssessor ();&lt;br /&gt;&lt;br /&gt;       System.err.println (&lt;span class="str"&gt;"\tTotal, Method, Field, Ratio"&lt;/span&gt;);&lt;br /&gt;       &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; n=1, total = 0; n &amp;lt; 10000000; n=2*n) {&lt;br /&gt;           final &lt;span class="kwrd"&gt;long&lt;/span&gt; t0 = System.nanoTime();&lt;br /&gt;           &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++) {&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; ((mv.getField() &amp;amp; 0x101) != 0)&lt;br /&gt;                   mv.setField(mv.getField()+1);&lt;br /&gt;               &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                   mv.setField(mv.getField()+2);&lt;br /&gt;           }&lt;br /&gt;           final &lt;span class="kwrd"&gt;long&lt;/span&gt; t1 = System.nanoTime();&lt;br /&gt;           &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++) {&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; ((fv.field &amp;amp; 0x101) != 0)&lt;br /&gt;                   fv.field = (fv.field+1);&lt;br /&gt;               &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                   fv.field = (fv.field+2);&lt;br /&gt;           }&lt;br /&gt;           final &lt;span class="kwrd"&gt;long&lt;/span&gt; t2 = System.nanoTime();&lt;br /&gt;&lt;br /&gt;           &lt;span class="rem"&gt;// dispay stats&lt;/span&gt;&lt;br /&gt;           final &lt;span class="kwrd"&gt;double&lt;/span&gt; mvCycleTime = (&lt;span class="kwrd"&gt;double&lt;/span&gt;)(t1 - t0) / n;&lt;br /&gt;           final &lt;span class="kwrd"&gt;double&lt;/span&gt; fvCycleTime = (&lt;span class="kwrd"&gt;double&lt;/span&gt;)(t2 - t1) / n;&lt;br /&gt;           final &lt;span class="kwrd"&gt;double&lt;/span&gt; ratio = 100.0*fvCycleTime/mvCycleTime;&lt;br /&gt;           total +=n;&lt;br /&gt;           System.err.printf(&lt;span class="str"&gt;"% 12d,  %.3f,  %.3f,  %.2f%% %c\n"&lt;/span&gt;,&lt;br /&gt;                           total, mvCycleTime, fvCycleTime, ratio,&lt;br /&gt;                           (fv.field == mv.getField() ? &lt;span class="str"&gt;' '&lt;/span&gt; : &lt;span class="str"&gt;'!'&lt;/span&gt;));&lt;br /&gt;&lt;br /&gt;           Thread.sleep(500);&lt;br /&gt;       }&lt;br /&gt;   }&lt;/pre&gt;&lt;br /&gt;This code produces the following output (with -XX:+PrintCompilation):&lt;br /&gt;&lt;pre&gt;&lt;small&gt;&lt;br /&gt;   Total, Method, Field, Ratio&lt;br /&gt;          1,  5866.000,  1759.000,  29.99% &lt;br /&gt;          3,  5463.000,  405.500,  7.42% &lt;br /&gt;          7,  1925.500,  217.750,  11.31% &lt;br /&gt;         15,  1166.000,  156.250,  13.40% &lt;br /&gt;         31,  648.313,  123.938,  19.12% &lt;br /&gt;         63,  440.438,  110.250,  25.03% &lt;br /&gt;        127,  401.922,  103.547,  25.76% &lt;br /&gt;        255,  270.688,  106.156,  39.22% &lt;br /&gt;        511,  243.715,  95.785,  39.30% &lt;br /&gt;       1023,  225.525,  94.367,  41.84% &lt;br /&gt;       2047,  231.510,  142.017,  61.34% &lt;br /&gt;       4095,  232.009,  97.745,  42.13% &lt;br /&gt;&lt;span style="color:red;"&gt;  2       tmp.TestFieldVsMethod$MethodAssessor::getField (5 bytes)&lt;/span&gt;&lt;br /&gt;       8191,  227.914,  97.593,  42.82% &lt;br /&gt;&lt;span style="color:red;"&gt;  3       tmp.TestFieldVsMethod$MethodAssessor::setField (6 bytes)&lt;/span&gt;&lt;br /&gt;      16383,  238.234,  98.486,  41.34% &lt;br /&gt;&lt;span style="color:red;"&gt;  1%      tmp.TestFieldVsMethod::benchmark @ 44 (277 bytes)&lt;/span&gt;&lt;br /&gt;      32767,  13.628,  1.675,  12.29% &lt;br /&gt;      65535,  1.621,  1.666,  102.78% &lt;br /&gt;     131071,  1.611,  1.658,  102.88% &lt;br /&gt;     262143,  1.602,  1.655,  103.31% &lt;br /&gt;     524287,  1.599,  1.653,  103.41% &lt;br /&gt;    1048575,  1.897,  1.923,  101.40% &lt;br /&gt;&lt;span style="color:red;"&gt;  4       java.lang.String::charAt (33 bytes)&lt;/span&gt;&lt;br /&gt;    2097151,  1.606,  1.652,  102.88% &lt;br /&gt;    4194303,  1.595,  1.652,  103.52% &lt;br /&gt;    8388607,  1.595,  1.652,  103.53% &lt;br /&gt;   16777215,  1.595,  1.655,  103.76% &lt;/small&gt;&lt;br /&gt;&lt;/small&gt;&lt;/pre&gt;&lt;br /&gt;Notice how ratio dives down at around 30,000 mark:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qOaAwvezbUk/SJkaPM0kHhI/AAAAAAAAB8E/kYQaHl2G1IM/s1600-h/fieldvsmethod.GIF"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_qOaAwvezbUk/SJkaPM0kHhI/AAAAAAAAB8E/kYQaHl2G1IM/s400/fieldvsmethod.GIF" alt="" id="BLOGGER_PHOTO_ID_5231241290609597970" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;What that probably means is that field access code is compiled faster:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qOaAwvezbUk/SJkaVaFaIDI/AAAAAAAAB8M/FLSq1pP0FMk/s1600-h/fieldvsmethod1.GIF"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_qOaAwvezbUk/SJkaVaFaIDI/AAAAAAAAB8M/FLSq1pP0FMk/s400/fieldvsmethod1.GIF" alt="" id="BLOGGER_PHOTO_ID_5231241397249122354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Without knowing much about hotspot inner workings, I expected to see a sharper decline. &lt;br /&gt;I run this test on server version of Java 6 (1.6.0_10-beta-b25, 64 bit).&lt;/small&gt;&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-5385513620867522255?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5385513620867522255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5385513620867522255'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/08/update-on-direct-vs-method-access.html' title='Update on &quot;direct vs. encapsulated field access times&quot;'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qOaAwvezbUk/SJkaPM0kHhI/AAAAAAAAB8E/kYQaHl2G1IM/s72-c/fieldvsmethod.GIF' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-1083067629191800870</id><published>2008-08-05T16:41:00.000-07:00</published><updated>2008-09-02T11:41:14.517-07:00</updated><title type='text'>Java NIO with large data files</title><content type='html'>We have a tool that sequentially reads financial data from massive multi-gigabyte files. It performs a lot of bytes-to-long, bytes-to-double, and utf-string conversions that were implemented in optimized fashion on top of &lt;tt&gt;BufferedInputStream&lt;/tt&gt;. &lt;br /&gt;&lt;br /&gt;It turns out that replacing that code with NIO's &lt;tt&gt;MappedByteBuffer&lt;/tt&gt; processes 2 Gb file &lt;b&gt;twice faster&lt;/b&gt;, while memory consumption remains the same. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update:&lt;/strong&gt; I have been warned and it turned out to be true: Reading 20 Gb file shows reverse results. Now NIO version is &lt;b&gt;8x slower&lt;/b&gt; than "old" stream-based approach. In this case I implemented paging because Java NIO cannot map file regions larger than 2Gb at once (Integer.MAX_VALUE).&lt;br /&gt;&lt;br /&gt;On Windows XP 8K is a sweet spot for BufferedInputStream buffer size. Allocating larger buffer actually reduces performance significantly. May be size of mapped region has similar optimum.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-1083067629191800870?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/1083067629191800870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/1083067629191800870'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/08/java-nio-with-large-data-files.html' title='Java NIO with large data files'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-8589995140829597692</id><published>2008-08-05T10:27:00.000-07:00</published><updated>2008-08-05T13:56:31.702-07:00</updated><title type='text'>Direct field vs. Method access times</title><content type='html'>In my opinion there is no justification for using 'friendly' direct access to mutable class fields rather than getters and setters properties. I heard the following two arguments:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1. It makes performance-critical code run faster.&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;False. There is no benefit of direct access in frequently executed code. Chart below compares access time of direct field access to getters and setters.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qOaAwvezbUk/SJiaCYPfrKI/AAAAAAAAB78/IcITdbdmWYQ/s1600-h/fieldvsmethod.GIF"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_qOaAwvezbUk/SJiaCYPfrKI/AAAAAAAAB78/IcITdbdmWYQ/s400/fieldvsmethod.GIF" border="0" alt=""id="BLOGGER_PHOTO_ID_5231100332848688290" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, after 20,000 calls there is no difference in performance. This threshold is controlled by &lt;tt&gt;-XX:CompileThreshold&lt;/tt&gt; JVM argument. Core of the test:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        final &lt;span class="kwrd"&gt;long&lt;/span&gt; t0 = System.nanoTime();&lt;br /&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++) {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ((mv.getField() &amp;amp; 0x101) != 0)&lt;br /&gt;                mv.setField(mv.getField()+1);&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                mv.setField(mv.getField()+2);&lt;br /&gt;        }&lt;br /&gt;        final &lt;span class="kwrd"&gt;long&lt;/span&gt; t1 = System.nanoTime();&lt;br /&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++) {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ((fv.field &amp;amp; 0x101) != 0)&lt;br /&gt;                fv.field = (fv.field+1);&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                fv.field = (fv.field+2);&lt;br /&gt;        }&lt;br /&gt;        final &lt;span class="kwrd"&gt;long&lt;/span&gt; t2 = System.nanoTime();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;2. Direct field access reduces bureaucracy.&lt;/h3&gt;&lt;br /&gt;Read: I am too lazy to write getters and setters. Well, Eclipse and Netbeans have &lt;b&gt;"Encapsulate Field"&lt;/b&gt; and &lt;b&gt;"Generate getters and Setters"&lt;/b&gt; commands. And BTW, what none of free IDEs have is &lt;b&gt;"Find where modified"&lt;/b&gt; search for class fields.&lt;br /&gt;&lt;br /&gt;Having said that, I have no problems with &lt;tt&gt;public final&lt;/tt&gt; fields :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-8589995140829597692?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8589995140829597692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/8589995140829597692'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/08/direct-field-vs-method-access-times.html' title='Direct field vs. Method access times'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_qOaAwvezbUk/SJiaCYPfrKI/AAAAAAAAB78/IcITdbdmWYQ/s72-c/fieldvsmethod.GIF' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-1411720266914814036</id><published>2008-07-31T06:41:00.000-07:00</published><updated>2008-08-04T18:50:23.915-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bugparade'/><title type='text'>A bug in Sun's 64-bit hotspot compiler</title><content type='html'>A colleague of mine found a scary bug in Sun's hotspot compiler (64 bit version). It is  reproducible on several computers in our office (CPUs: 2x AMD Opteron, Intel E8400; OS: Windows XP Professional 64-bit). Here is the code:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FailingTest {&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; final java.io.RandomAccessFile raf;&lt;br /&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; sequence;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; FailingTest() throws Exception {&lt;br /&gt;        java.io.File f = &lt;span class="kwrd"&gt;new&lt;/span&gt; java.io.File(&lt;span class="str"&gt;"test.dat"&lt;/span&gt;);&lt;br /&gt;        f.delete();&lt;br /&gt;        raf = &lt;span class="kwrd"&gt;new&lt;/span&gt; java.io.RandomAccessFile(f, &lt;span class="str"&gt;"rw"&lt;/span&gt;);&lt;br /&gt;        f.deleteOnExit();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; test(&lt;span class="kwrd"&gt;long&lt;/span&gt; timestamp) throws Exception {&lt;br /&gt;        &lt;span class="rem"&gt;// This condition never happens but is required to&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// reproduce this bug, so is unused timestamp argument&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (timestamp &amp;lt; 0)&lt;br /&gt;            System.exit(0);&lt;br /&gt;&lt;br /&gt;        final &lt;span class="kwrd"&gt;long&lt;/span&gt; valueToStore = sequence++;&lt;br /&gt;        raf.seek(0);&lt;br /&gt;        raf.writeLong(valueToStore);&lt;br /&gt;        raf.seek(0);&lt;br /&gt;        final &lt;span class="kwrd"&gt;long&lt;/span&gt; valueRead = raf.readLong();&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (valueRead != valueToStore)&lt;br /&gt;            System.err.println(&lt;span class="str"&gt;"Error: Read value "&lt;/span&gt; +&lt;br /&gt;                            valueRead + &lt;span class="str"&gt;" != "&lt;/span&gt; + valueToStore);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; main (String [] args) throws Exception {&lt;br /&gt;        FailingTest t = &lt;span class="kwrd"&gt;new&lt;/span&gt; FailingTest();&lt;br /&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; ii = 0; ii &amp;lt; 1000000; ii++)&lt;br /&gt;            t.test(ii);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On my machine this test fails with the following output (I run it with &lt;tt&gt;-server -XX:CompileThreshold=100&lt;/tt&gt;):&lt;br /&gt;&lt;pre style='font-color=red'&gt;&lt;br /&gt;Error: Read value 4826 != 4825&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The test fails every time with different numbers, with any version of 64-bit Sun JDK 1.6 we tried. This problem is NOT reproducible under 32-bit version and NOT reproducible on BEA's JRockit 1.6 (64 bit). Just verified that problem remains on the latest JVM available: build 1.6.0_10-beta-b25, Java HotSpot(TM) 64-Bit Server VM (build 11.0-b12, mixed mode).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-1411720266914814036?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/1411720266914814036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/1411720266914814036'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/07/64-bit-jvm-hotspot-bug.html' title='A bug in Sun&apos;s 64-bit hotspot compiler'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-9159428550334256518</id><published>2008-07-21T14:58:00.000-07:00</published><updated>2008-07-21T21:17:52.526-07:00</updated><title type='text'>Debug mode penalty in .NET and Java</title><content type='html'>Java users quite often distribute their code compiled in debug mode. This improves error diagnostics while performance penalty for having debug information in class files is negligible. Java doesn't have compile-time optimization since version 1.3 (for 8 years by now).&lt;br /&gt;&lt;br /&gt;That is why I was amazed to see that C# Debug version of my test was &lt;b&gt;14.5 times slower&lt;/b&gt; compared to Release (compiled as &lt;tt&gt;/optimize+ /checked- /debug-&lt;/tt&gt;). I  could have imagined such difference for C++, but not for C# that also has just-in-time (JIT) optimization at run-time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-9159428550334256518?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/9159428550334256518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/9159428550334256518'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/07/debug-mode-penalty-in-net-and-java.html' title='Debug mode penalty in .NET and Java'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-3258962590905305522</id><published>2008-07-07T15:44:00.000-07:00</published><updated>2008-07-07T15:53:27.924-07:00</updated><title type='text'></title><content type='html'>&lt;img src="http://img.photobucket.com/albums/v484/giddygen/1491224690_5157d5f010.jpg" border="0"/&gt;&lt;br /&gt;&lt;a ref="http://www.ralphlgoings.com"&gt;Ralph Goings  "cream pie" oil on canvas, 1979&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-3258962590905305522?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3258962590905305522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/3258962590905305522'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/07/ralph-goings-cream-pie-oil-on-canvas.html' title=''/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-467669055659896545</id><published>2008-06-12T09:43:00.000-07:00</published><updated>2008-06-12T20:43:16.081-07:00</updated><title type='text'>Ant task for IKVMC</title><content type='html'>&lt;p&gt;Submitted Ant task for IKVMC - &lt;a href="http://ant-ikvmc.sourceforge.net/"&gt;ant-ikvmc&lt;/a&gt;. I found multiple &lt;tt&gt;FileSet&lt;/tt&gt; elements in Ant more convenient in defining source classes than &lt;tt&gt;-recurse:mask&lt;/tt&gt; command line argument provided by &lt;a href="http://www.ikvm.net/userguide/ikvmc.html"&gt;IKVMC&lt;/a&gt;.&lt;p&gt;Example of task:&lt;pre&gt;&amp;lt;ikvmc target="library" out="${dotnet.out}/uhfclient.dll" home="${ikvm.home}" version="1.0.0.0" debug="true"  verbose="true"&amp;gt;&lt;br /&gt;   &amp;lt;reference path="${dotnet.out}/uhfc-3rd-party.dll"/&amp;gt;&lt;br /&gt;   &amp;lt;fileset dir="${classes}" includes="${uhfdll.resources}"&amp;gt;&lt;br /&gt;     &amp;lt;exclude name="**/*.vpp"/&amp;gt;&lt;br /&gt;     &amp;lt;exclude name="**/*.txt"/&amp;gt;&lt;br /&gt;   &amp;lt;/fileset&amp;gt;&lt;br /&gt;   &amp;lt;fileset dir="${jars}"&amp;gt;&lt;br /&gt;       &amp;lt;include name="**/*.jar"/&amp;gt;&lt;br /&gt;       &amp;lt;exclude name="foo.jar"/&amp;gt;&lt;br /&gt;   &amp;lt;/fileset&amp;gt;&lt;br /&gt; &amp;lt;/ikvmc&amp;gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Bonus: Java doclet that generates IKVMC mapping file. Among other things mapping file can specify parameter names in methods and constructors translated by IKVMC. Since Java parameter names are not available from Java class files, IKVMC needs this hint to preserve original Java names. This is handy if you generate API libraries that will be used by .NET developers.&lt;/p&gt;&lt;p&gt;Here is an example of javadoc task to generate IKVM mapping file for selected packages:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;lt;javadoc sourcepath="${src}" classpath="${javac.classpath}" defaultexcludes="yes"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;doclet name="deltix.tools.ikvmc.ant.IkvmcMapDoclet" path="${classes}"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;param name="-out" value="${mapfile}"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/doclet&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;package name="com.acme.api"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;package name="com.acme.util"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/javadoc&amp;gt;&lt;/pre&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-467669055659896545?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/467669055659896545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/467669055659896545'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/06/ant-task-for-ikvmc.html' title='Ant task for IKVMC'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-5538925358388538297</id><published>2008-06-12T09:27:00.000-07:00</published><updated>2008-06-25T13:57:53.851-07:00</updated><title type='text'>IKVM for Java - .NET interoperability</title><content type='html'>&lt;p&gt;Front-end to our Java-based server is written on C#/.NET. Interoperability is achieved using XML/WS-based server API (as well as some custom binary format for high volume data responses). Typical architecture. Well, this is going to change now, after we discovered &lt;a href="http://www.ikvm.net/"&gt;IKVM&lt;/a&gt; project. IKVM translates Java byte code into MSIL.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The lack of Microsoft Java implementation for .NET platform has obvious commercial reason. But what cannot be done by the largest software company was done by single developer - Jeroen Frijters (the man behind IKVM). Amazing.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-5538925358388538297?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5538925358388538297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5538925358388538297'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/06/ikvm-for-java-net-interoperability.html' title='IKVM for Java - .NET interoperability'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-5432054024245769891</id><published>2008-06-12T08:39:00.000-07:00</published><updated>2008-06-12T10:32:36.523-07:00</updated><title type='text'>JAXB 2.1 is now in Java 6 (almost)</title><content type='html'>&lt;p&gt;Looks like Sun folks silently updated Java 6 to use JAXB 2.1 API. The fact that Java 6 was shipped with old version of JAXB used to be a lot of &lt;a href="http://weblogs.java.net/blog/kohsuke/archive/2007/02/running_jaxbws.html"&gt;pain&lt;/a&gt;. Hopefully we don't need to mess with endorsed directory workaround anymore.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I run a diff and it turns out that JAXB API shipped with JDK 1.6 is almost identical to 2.1. It has only one significant difference from 2.1.6: Class &lt;tt&gt;javax.xml.bind.ContextFinder&lt;/tt&gt; refers to a different location of Context Factory. In com.sun.xml.internal.bind.* became com.sun.xml.bind.*&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Bottom line: if you want to use JAXB 2.1 with 1.6, simply add JAXB implementation in your classpath. No need to use Java endorsed mechanism anymore.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;P.S. Also the following frequent error is now a history: "&lt;tt&gt;java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader, but this RI requires 2.1&lt;/tt&gt;". If you still see it with JAXB 2.1 in classpath simply update your Java 6 to the latest version (I tested it with 1.6.0_04-b12+ which was released in Spring 2008).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-5432054024245769891?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5432054024245769891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/5432054024245769891'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/06/jaxb-21-is-now-in-java-6-almost.html' title='JAXB 2.1 is now in Java 6 (almost)'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-4891703498647542484</id><published>2008-06-02T13:48:00.000-07:00</published><updated>2008-06-12T09:27:08.704-07:00</updated><title type='text'>JAXB error "java.lang.StackTraceElement does not have a no-arg default constructor"</title><content type='html'>&lt;p&gt;Our Java-based XML service responds with exceptions in case of errors, so naturally it serializes subclasses of &lt;tt&gt;java.lang.Exception&lt;/tt&gt; to XML.&lt;/p&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Unfortunately JAXB 2.1.x fails when someone attempts to marshal a subclass of Exception:&lt;tt&gt;java.lang.StackTraceElement does not have a no-arg default constructor&lt;/tt&gt;. This can be fixed using mechanism of &lt;a href="http://wiki.jboss.org/wiki/JAXBIntroductions"&gt;JAXB Introductions&lt;/a&gt;. I just posted a fix &lt;a href='http://forums.java.net/jive/thread.jspa?messageID=278047'&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-4891703498647542484?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/4891703498647542484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/4891703498647542484'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/06/jaxb-error-javalangstacktraceelement.html' title='JAXB error &quot;java.lang.StackTraceElement does not have a no-arg default constructor&quot;'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-8668853818783919860.post-7103721304844828342</id><published>2008-05-20T16:01:00.000-07:00</published><updated>2008-06-12T17:07:30.797-07:00</updated><title type='text'>FP :-)</title><content type='html'>I hope this blog will motivate me to finish all these little notes that ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8668853818783919860-7103721304844828342?l=andy-malakov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/7103721304844828342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8668853818783919860/posts/default/7103721304844828342'/><link rel='alternate' type='text/html' href='http://andy-malakov.blogspot.com/2008/05/fp.html' title='FP :-)'/><author><name>Andy Malakov</name><uri>http://www.blogger.com/profile/13571272251116627683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_qOaAwvezbUk/Smfd1dk8NDI/AAAAAAAADwg/cQ2wXlLZ5xA/S220/AvatarCanyon.JPG'/></author></entry></feed>
