Monday, 24 April 2017

JVM heap size in 64 bit environment: Compressed OOP and beyond 32GB heap size

In a 32 bit there are many constraints on memory a JVM can use. The total addressable memory is just 2^32 = 4GB and then there is memory reserved for OS. Further, out of this memory available to java process, some is needed for PermGen, threads etc so the JVM can only use a much smaller memory as heapsize. See java-process-memory-jvm-heap-size for details.

Now in a 64 bit environment we do not have such constraints, since total addressable memory is more than 18 EB (2^64 = 2^4x(1024)^6 = 16 Exbibyte ~ 18x10^18 Bytes). Most of the java based enterprise applications do not need to go beyond 32 GB (besides the hardware constraints) so there is plenty of room left. However, there are some unexpected challenges. One such is increased memory usage because of expanded size of managed pointers (ordinary object pointer) so same application can take upto 1.5 times the heap on 64 bit platform after switching from a 32 bit platform.

Now managed pointers are aligned to 8byte address boundaries so managed pointers are addresses - 0, 8, 16, 24, 32, ... (ie 000000, 001000, 010000,11000,100000,...) and so on. To "compress" these pointers JVM developers used this strategy - scale down the address by a factor of 8 (ie left shift bits by 3 places) to get compressed pointers - 0, 1, 2, 3, 4,... (000,001,010,011,100,...) and so on. Using this strategy up to a 35 bits of a 64 bit address can be "compressed" into a 32 bit word (half word on 64 bit architecture). 

So using a Compressed OOP we can address 2^35 objects = 32 GB of heap space. Java SE 6u23 and later 64 bit JVM uses compressed OOP by default. However going beyond 32 GB of heap size will cause JVM to switch to regular OOP with increased size so total number of objects that can be referenced actually goes down even though heap size is increased. How big is this performance drop? This blog here shows around 48 GB was required to accommodate same number of objects as a 32 GB heap (with CompressedOOPs). So basically most java applications will see performance drop between 32 GB and ~ 48 GB!

There are other issues in going to large heap sizes like Garbage collection but that is a discussion for some other time.

Also see:



Wednesday, 4 May 2016

System32, SysWOW64 and Sysnative: File System Redirector



It can get a little confusing with different file redirection provided by windows to access 32 and bit libraries in a 64 bit Windows system. This post in intended to just provide a concise summary of when to us which path. More details can be found in links given in reference section.

System32: Contains 64 bit dlls and executables and 64 bit applications can access them by putting system32 in their target path.
So a 64 bit application can call 64 bit powershell by using this path:
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe

SysWOW64: Contains 32 bit dlls and executables. So 64 bit applications can access these by putting syswow64 in their target path. 32 bit applications will be redirected to this folder if they make a call with system32 in the target path.
So a 64 bit application can access the 32 bit version of powershell by going to this path:
%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe

Note: if a 32 bit application makes a call to System32 it is automatically redirected to SysWOW64.

Sysnative: is a virtual folder, a special alias used to indicate that the file system should not redirect the access to SysWOW64
So a 32 bit application can call 64 bit version of powershell by using this path:
%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe



Source\Target
64 bit
32 bit
64 bit
system32
syswow64
32 bit
sysnative
system32/syswow64


http://www.samlogic.net/articles/sysnative-folder-64-bit-windows.htm
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx

Thursday, 7 August 2014

XPATH to check if a given node is present or not

To check if a node is present in a XML or not simply use boolean function

So for the XML


<person id="1"> <name>John Smith</name> <phone_home>12345</phone_home> <phone_office></phone_office> </person>





If we want to know if phone_home is present or not then simply say

boolean(/person/phone_office)

Similarly if you want to check if any phone is present or not

boolean(/person/*[contains(name(.),"phone")])

and in the same way it can be extended to more complex queries, like if any phone is empty

boolean(/person/*[contains(name(.),"phone") and .=""])

or if any or the nodes are empty:

boolean(/person/*[.=""])


Same approach can be applied based on node content.

So for XML


<jobs> <job seq="1">Job 1 Completed with status success</job> <job seq="2">Job 2 Completed with status success</job> <job seq="3">Job 3 Completed with status failure</job> <job seq="4">Job 4 Completed with status success</job> </jobs>







If we need to know if any of the jobs failed:

boolean(/jobs/job[contains(.,"status failure")])

Also, the same approach can be used based on attribute name

So for XML


<details> <detail name="John Smith"/> <detail phone_home="12345"/> <detail phone_office="54321"/> </details>






If we need to know if any of the attribute has phone in attribute name then:

boolean(/details/detail[contains(name(./@*), "phone")])

And same as with node names we can check if any of phone is empty:

boolean(/details/detail[contains(name(./@*), "phone") and ./@* = ""])

or if any of the attribute is empty

boolean(/details/detail[./@* = ""])

Hope this helps

Thursday, 23 January 2014

Java process memory: JVM heap size constraints in 32 bit environment

In theory, on a given computer system, the addressable memory is 2^b bytes where b is bit of the processor architecture. (Although there is much more to it like PAE and stuff. )

So maximum physical memory in a 32 bit is:
2^32 = 4X(1024)X(1024)X(1024) Bytes = 4096 MB = 4 GB

Out of this 4 GB some of the memory is reserved for OS, amount varies from OS to OS. So the maximum memory any process can occupy is less than 4GB. Further, in case of java process there are other components to the memory usage - JVM heap, PermGen space and native threads.

Roughly,
JVM Heap Size + PermGen Space + (Thread stack size*number of thread) < Maximum space OS allows for processes.

So there is limit on the maximum heap size you can have practically which depends on the underlying OS.

I did a few tests to check what is the result of requesting different Max heap size values on different systems. Following table lists result of different Xmx values for each of those systems:


Xmx (CentOS 32 bit)Xmx (Ubuntu 32 bit)Xmx (RHEL 64 bit)Xmx (Win7 64 bit)Xmx (Win XP 32 bit)Xmx (SunOS 32 bit)Result
> 4095m> 4095m> 4095m> 4095m> 4095m> 4095mThe specified size exceeds the maximum representable size.
4095m4095m4095m4095m4095m4095mIncompatible minimum and maximum heap sizes specified
4030m - 4094m4030m - 4094m4030m - 4094m4000m - 4094m4000m - 4094m4000m - 4094mThe size of the object heap + VM data exceeds the maximum representable size
2700m - 4030m2685m - 4030m3730m - 4030m1500m - 4000m1460m - 4000m3750m - 4000mCould not reserve enough space for object heap
< 2700m (approx)< 2685m (approx)< 3730m (approx)< 1500m (approx)< 1460m (approx)< 3750mJVM initialized

Little more on the results:
  1. So when you try to go above 4096M (ie 4GB) the  error is "The specified size exceeds the maximum representable size." Which is expected since 4GB is maximum addressable memory.
  2. At 4095M, strangely it says "Incompatible minimum and maximum heap sizes specified", looks like value 4095 is regarded same as 0. I am not sure on this, need to do more research.
  3. From roughly 4000m to 4094m it says "The size of the object heap + VM data exceeds the maximum representable size" which is again understandable since as mentioned before java process has other components too so overall java process size is going beyond 4096M (the limit on addressable memory)
  4. Going lower on heap, we have "Could not reserve enough space for object heap" so now we see those OS specific limits. Each OS allows a different amount of memory for a process and subtracting the non-heap part of java process we get the limit on heap size. Even the non heap part (thread stack size and limit on threads) is OS specific.

All of these tests were performed using 32 bit jdk1.7.0_04 with default PermGen space and default thread stack size and thread limits. If you tweak these heap size can be increased a little.
So in the limited test environments (with default settings) the trend is roughly as following:
  • OS being 32 bit or 64 bit has very little bearing on the results.
  • Server class Unix based OS (SunOS and RHEL) > Desktop Linux (Ubuntu, CentOS) > Windows Desktop (Win7, WinXP)
Need to check this on Windows Servers too but i think results will be between Windows desktop and Linux desktop values but closer to windows desktop OS.

Wednesday, 1 January 2014

Evaluate XPATH in Java

This is straight forward and I think better than iterating through the document tree. There is a evaluate method available in XPATH interface.

Here is a sample code for it:

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;


public class ApplyXPATH {

    public static void main(String[] args) {
        XPath xpath = XPathFactory.newInstance().newXPath();
        InputSource inputSource = new InputSource("XMLs/MultiNode.xml");
        String expression = "//node/data";
        NodeList outPut=null;
        try {
            outPut = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        for(int i=0; i<outPut.getLength();i++) {
            System.out.println(outPut.item(i).getFirstChild().getNodeValue());
        }
    }
}


Sample Input:
<root>
    <node>
        <data>123</data>
        <data>456</data>
        <junk>abc</junk>
    </node>
    <junknode>
        <junk>def</junk>
    </junknode>
    <node>
        <data>789</data>
        <junk>ghi</junk>
        <data>012</data>
    </node>
</root>


Sample Output:
123
456
789
012

Here I am just printing the node values but you can easily create a new XML document and append this nodelist to it.

PS: if you change the expression to //node/data/text() then to access the value you just need to do outPut.item(i).getNodeValue()

Tuesday, 31 December 2013

Recursive XSLT: Concat Multiple Nodes

Sharing this XSLT which I used couple of years back to concat a node set. The usecase was to extract a specific node set and concatenate their values.

Sample Input:
<root>
    <node>
        <data>123</data>
        <data>456</data>
        <junk>abc</junk>
    </node>
    <junknode>
        <junk>def</junk>
    </junknode>
    <node>
        <data>789</data>
        <junk>ghi</junk>
        <data>012</data>
    </node>
</root>


Desired Output:
<out>
  <mssg>123456789012</mssg>
  <junk>abcdefghi</junk>
</out>


XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="yes" />
  <xsl:template match="/">
    <out>
      <xsl:variable name="mssg_data">
        <xsl:call-template name="ConCat">
          <xsl:with-param name="List" select="/root/node/data" />
        </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="junk_data">
        <xsl:call-template name="ConCat">
          <xsl:with-param name="List" select="//junk" />
        </xsl:call-template>
      </xsl:variable>
      <mssg>
        <xsl:value-of select="$mssg_data" disable-output-escaping="no" />
      </mssg>
      <junk>
        <xsl:value-of select="$junk_data"/> 
      </junk>
    </out>
  </xsl:template>
  <xsl:template name="ConCat">
    <xsl:param name="List" />
    <xsl:param name="result" select="''" />
    <xsl:choose>
      <xsl:when test="$List">
        <xsl:call-template name="ConCat">
          <xsl:with-param name="List" select="$List[position() &gt; 1]" />
          <xsl:with-param name="result" select="concat($result, $List[1])" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$result" disable-output-escaping="no" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>


Note: The similar result can be achieved by using XPATH evaluator to get text of data node set (ie /root/node/data/text()), depending on the requirement one or the other approach may be more suitable.

Monday, 30 December 2013

Looping in XSLT: Recursive Template Calls

To loop in XSLT you need to call a template recursively.

In past I have done this using two approaches:

Option-1: While Loop
Logic is similar to a while loop. So the counter is decremented till it is greater than 0.
 
 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="no" />
  <xsl:template match="/">
    <LoopInput>
      <xsl:call-template name="CreateLoop">
        <xsl:with-param name="count" select="${numLoop}" />
      </xsl:call-template>
    </LoopInput>
  </xsl:template>
  <xsl:template name="CreateLoop">
    <xsl:param name="count" />
    <xsl:if test="$count &gt; 0">
      <xsl:call-template name="CreateLoop">
        <xsl:with-param name="count" select="$count - 1" />
      </xsl:call-template>
      <Line>
        <xsl:text disable-output-escaping="no">Line Data: </xsl:text>
        <xsl:value-of select="$count" disable-output-escaping="no" />
      </Line>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>


Option-2: For Loop
Here counter is incremented from a initial count till it reaches the desired loop count.

 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="no" />
  <xsl:template match="/">
    <LoopInput>
      <xsl:call-template name="CreateLoop">
        <xsl:with-param name="MaxLoop" select="${numLoop}" />
        <xsl:with-param name="iLoop" select="1" />
      </xsl:call-template>
    </LoopInput>
  </xsl:template>
  <xsl:template name="CreateLoop">
    <xsl:param name="MaxLoop" />
    <xsl:param name="iLoop" />
    <Line>
      <xsl:text disable-output-escaping="no">Line Data: </xsl:text>
      <xsl:value-of select="$iLoop" disable-output-escaping="no" />
    </Line>
    <xsl:if test="$iLoop &lt; $MaxLoop">
      <xsl:call-template name="CreateLoop">
        <xsl:with-param name="MaxLoop" select="$MaxLoop" />
        <xsl:with-param name="iLoop" select="$iLoop + 1" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>