<?xml version="1.0"?>
<rss version="2.0">
<channel>
  <title>Coding the Architecture - gc tag</title>
  <link>http://www.codingthearchitecture.com/tags/gc/</link>
  <description>Software architecture for developers</description>
  <language>en</language>
  <copyright>Coding the Architecture</copyright>
  <lastBuildDate>Wed, 16 May 2012 08:01:04 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  
  
  <item>
    <title>JVM Lies: The OutOfMemory Myth</title>
    <link>http://www.codingthearchitecture.com/2008/01/14/jvm_lies_the_outofmemory_myth.html</link>
    
      
        <description>
          &lt;P&gt;
There are times when an OutOfMemoryError means exactly what it says.  Try adding new objects to an ArrayList in a while(true) loop and you&#039;ll see what I mean.
&lt;/P&gt;&lt;P&gt;
However, there are times when it doesn&#039;t.
&lt;/P&gt;&lt;P&gt;
Recently, when I saw a vital supporting application of our system throwing an OutOfMemoryError in production, my first instinct was to increase the &lt;code&gt;-Xmx&lt;/code&gt; switch from the existing 2GB.  Let&#039;s whack on an extra gig, why not.  That will give us at least 6 months until we start worrying about the logical 4GB limit of a 32-bit process&#039;s addressable space.
&lt;/P&gt;&lt;P&gt;
I expect I am not alone in having the knee-jerk reaction that any application&#039;s memory problems can be solved by cranking up the heap.  I blame James Gosling, or whoever decided that the JRE 1.1 JVM&#039;s heap should default to 64M.  Even at the start of my Java programming career in 1998 I remember quickly running out of heap space, and needed to look up what this &lt;a href=&#034;http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp&#034;&gt;non-standard&lt;/a&gt; &lt;code&gt;-Xmx&lt;/code&gt; switch did.  Increasing this value made these problems just disappear.
&lt;/P&gt;&lt;P&gt;
However, instead of doing the obvious and increasing the -Xmx, I added extra GC debugging output and attempted to replicate the problem.  We have plenty of spare memory on our hardware, so any time spent on such an obvious issue is arguably a waste: there was important business functionality I could be delivering instead of messing around with JVM switches.  However, being at times more stubborn than my own good, I insisted on understanding exactly what was going on.  In particular:
&lt;/P&gt;&lt;ol&gt;
&lt;li&gt;Why was similar behaviour not occurring in the test environment?&lt;BR/&gt;

	I am blessed with comparable hardware, and data volumes, in a test environment as the production environment.  A rare treat, I appreciate, but an invaluable one for situations such as this.  Well it turns out the answer to this question was straightforward: it was.  The flaw was with our monitoring of this environment.  Abashed, I made a mental note to improve our application monitoring and moved on to question 2.
	&lt;/li&gt;
&lt;li&gt;Why were we running out of memory?&lt;BR/&gt;

	Data volumes increase in the system on a monthly basis, so the answer to this question may seem self-evident. Without correct monitoring and re-tuning, our JVMs are &lt;i&gt;expected&lt;/i&gt; to run out of memory.  This isn&#039;t necessarily an architectural flaw, it&#039;s simply about allocating the right amount of memory for the current data volumes.  However, I had to be sure it was the heap that we were running out of.
&lt;/li&gt;&lt;/ol&gt;
&lt;P&gt;
Depending on the flavour of JVM, an OutOfMemoryError can indicate a shortage of memory in one of several areas.  These broader concepts are common to generational GC algorithms across the major JVM vendors including Sun, IBM and BEA, although the specifics I refer to below relate to the &lt;a href=&#034;http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html&#034;&gt;Sun Hotspot GC model&lt;/a&gt;.
&lt;/P&gt;&lt;ul&gt;
&lt;li&gt;
The first is the tenured generation.  This is usually what I mean when I say &#034;the heap&#034;.  Memory is segmented into several generations, however it is when the tenured generation is full, and cannot be expanded any further, that the JVM considers itself OutOfMemory.
&lt;/li&gt;&lt;li&gt;
The second is the permanent generation.  This does not resize during the life time of the application, regardless of how much free space may exist in the rest of the heap, but remains at whatever it was originally set to (default is 64K).  Should this prove too small for the perm generation, then the JVM will throw an OOME even if there&#039;s plenty of heap left.  Adding the &lt;code&gt;-XX:+PrintHeapAtGC&lt;/code&gt; switch will tell you if this is the case.
&lt;/li&gt;&lt;li&gt;
The third possibility is your operating system is out of memory, e.g. you&#039;ve asked for a 2GB heap on a box with 1GB RAM and 512MB swap space (not a typical server, admittedly, but serves as an example).
&lt;/li&gt;&lt;/ul&gt;
In my case I was primarily investigating which of the first two above scenarios was occurring (I knew we had enough spare memory on the box itself), so I was somewhat surprised to find out it was neither.
&lt;ul&gt;&lt;li&gt;
Another possibility is native components are hogging your 4GB ceiling.  Native code competes with the JVM to use the 4GB of addressable space in your application.  If these components are memory hungry, your app will be starved of addressable space, even if it hasn&#039;t actually used up all the heap you&#039;ve given it yet.  This may manifest itself during the workings of the Hotspot JIT compiler, which itself is a native component, as the Just In Time compiler uses some of your process&#039;s space to compile methods to native code at runtime.  Should these memory requirements push the addressable space required in the process above 4GB, then you get an OOME thrown which the 1.4 JVM logs as:
&lt;/P&gt;
&lt;code&gt;
Exception in thread &#034;CompilerThread0&#034; java.lang.OutOfMemoryError: requested&lt;BR/&gt;
Exception in thread &#034;main&#034; java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?&lt;BR/&gt;
&lt;/code&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;P&gt;
The process hadn&#039;t used all the space available to it when I saw this error -- the Java heap had plenty of room left unused.  However for addressing purposes this space was considered consumed.
&lt;/P&gt;&lt;P&gt;
So, what to do about the above error?  Increasing the heap allocation actually exacerbates this problem! It decreases the headroom the compiler, and other native components, have to play with.
&lt;/P&gt;&lt;P&gt;
So the solution to my problem was:&lt;/P&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;i&gt;reduce&lt;/i&gt; the heap allocated to the JVM.
	&lt;/li&gt;&lt;li&gt;
	remove the memory leaks caused by &lt;a href=&#034;http://www.codingthearchitecture.com/2008/01/08/the_clash_of_the_paradigms.html&#034;&gt;native objects not being freed in a timely fashion&lt;/a&gt;.
	&lt;/li&gt;
&lt;/ol&gt;
&lt;P&gt;
Or just use a 64-bit JVM.
&lt;/P&gt;
        </description>
      
      
    
    
    
    <comments>http://www.codingthearchitecture.com/2008/01/14/jvm_lies_the_outofmemory_myth.html#comments</comments>
    <guid isPermaLink="true">http://www.codingthearchitecture.com/2008/01/14/jvm_lies_the_outofmemory_myth.html</guid>
    <pubDate>Mon, 14 Jan 2008 13:39:00 GMT</pubDate>
  </item>
  
  <item>
    <title>The Clash of the Paradigms</title>
    <link>http://www.codingthearchitecture.com/2008/01/08/the_clash_of_the_paradigms.html</link>
    
      
        <description>
          &lt;p&gt;
I recently came across a subtle anti-pattern which has caused me some pains.  This occurred in a successful application used extensively throughout a large financial corporation.  It is a library, which is implemented in C++, but usable from several different programming languages, including Java and C#.
&lt;/p&gt;&lt;p&gt;
The Java port is a thin layer of Java objects which are used as proxies making JNI calls to underlying C++ objects.
&lt;/p&gt;&lt;p&gt;
At first glance this is an understandable design: the vast majority of the API&#039;s source code is written in one language, and the thin layers used to port the API are presumably easy to maintain.
&lt;/p&gt;&lt;p&gt;
But it all goes to pot when you consider garbage collection.  How does a native object know that it is no longer needed?  Well, when there&#039;s no more references to the proxy, of course!  But there&#039;s the rub: the only way a proxy can implicitly determine it is not needed is through a finalize method*.  This method is &lt;a href=&#034;http://java.sun.com/javase/6/docs/api/java/lang/Object.html#finalize()&#034;&gt;clearly documented&lt;/a&gt; to offer no guarantees of when it is invoked; this is likely to be at the mercy of the garbage collector, which in itself implies that at best several potentially-infrequent garbage collection cycles are required before such methods are called.
&lt;/p&gt;&lt;p&gt;
Consider the case when you have many thin Java objects which each create enormous native data structures: the JVM may not invoke a GC cycle on the modest memory usage of the Java objects, and in the meantime zombie native components may have used up all the swap space available.
&lt;/p&gt;&lt;p&gt;
The only reasonable alternative is to expose a delete() method in the Java API which is to be explicitly called when the application knows that the native object is no longer required, which in turn frees the native memory used.  However, for Java programmers used to their memory-managed sandboxes this goes strongly against the grain.  The 3rd party native objects, so innocently wrapped up in Java proxies, quickly spread like a virus throughout large tracts of code.  The package in question also, for performance reasons, exposes objects at a relatively fine-grained level, further facilitating its own objects&#039; insinuation throughout the application.  What&#039;s left is a soup of objects, of which some are POJOs, and some hide native objects and must have their lifecycles carefully tracked to be cleaned up appropriately.  Get it wrong and free an object prematurely, and you core-dump the JVM and bring down your application spectacularly, irrevocably and catastrophically.  Eliminating memory leaks in your Java code has become a major task.
&lt;/p&gt;&lt;p&gt;
Admittedly, the impact of the library can be reduced by carefully considered abstractions in client code.  But I can&#039;t help but blame the designers of the API who enforce their paradigm of programming on all clients of their system.  What may be an excellent object-oriented API in C++ does not make a good API in Java.  The lesson here is for architects not only to consider the functionality and aesthetics of their API, but also the programming paradigm which suits their clients.
&lt;/p&gt;&lt;p&gt;
*Tony Printezis has published an &lt;a href=&#034;http://java.sun.com/developer/technicalArticles/javase/finalization/&#034;&gt;alternative for finalizers by using weak references&lt;/a&gt;.  As the author says, it involves implementing an algorithm, running on its own thread, duplicating functionality provided by the garbage collector, in application code.

&lt;/p&gt;
        </description>
      
      
    
    
    
    <category>How do you define software architecture?</category>
    
    <comments>http://www.codingthearchitecture.com/2008/01/08/the_clash_of_the_paradigms.html#comments</comments>
    <guid isPermaLink="true">http://www.codingthearchitecture.com/2008/01/08/the_clash_of_the_paradigms.html</guid>
    <pubDate>Tue, 08 Jan 2008 10:29:00 GMT</pubDate>
  </item>
  
  </channel>
</rss>

