Garbage Collector Pitfalls

Posted 2009-03-04 in Java by Johann.

Garbage

Garbage by Editor B, some rights reserved.

If your Java VM crashes, your application might leak memory or the memory settings might not be optimal.

Whatever the cause might be, the following tips will help you fix the problem quickly.

Don’t increase Maximum Memory

Many developers’ first reaction if the Java VM isn’t stable is to increase the maximum memory with the -Xmx switch. The problems of this are:

  • Garbage collections take longer since more memory needs to be cleaned, leading to a lower application performance.
  • Memory leaks take longer to crash the VM. If there is a memory leak, having a larger Java heap means it will take longer until the VM crashes, making testing more difficult.

Enable GC logging

Keeping an eye on what the garbage collector is doing is important. In my experience, the runtime overhead is small so I have this enabled at all times. If logging is not enabled and a crash happens, it might take a long time to reproduce it.

For the Sun VM, add the following switches:

-Xloggc:<file> -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 

You can analyze the garbage collector log file using GCViewer or a variety of other tools.

For the IBM VM, add the following switches:

-Xverbosegclog:<file>

The output of the IBM VM is written in an XML format. Pay attention to the nursery and tenured elements and their freebytes attribute. A complete description is available in the Diagnosis documentation.

Adapt the ratio of “New” to “Old” space

Without diving too deep into the Java memory model, let me just say there is a “new” space for newly created objects and an “old” space for objects that have been used for a while.

Web applications usually create many objects that are only used for a short time during a request. If the ratio of “new” to “old” is too low, many garbage collections will occur, decreasing the application performance.

An easy way to test this is to watch the garbage collector log file (tail –F <log file>) and click on a button. If you see more than one garbage collection, there might not be enough “new” space. In this case, increasing the ratio of “new” to “old” might help a lot.

For the Sun VM, the switch is:

-XX:NewRatio=<ratio>

I have this set on this server to -XX:NewRatio=2, making “new” one third the size of “old.”

For the IBM VM, the switches are:

-Xmnx=<maximum new size> -Xmx=<maximum overall Java heap size>

Did you have problems with garbage collection? Post a comment how you solved them!

5 comments

Permanent and Temporary Redirects in Java (Servlet/JSP)

Posted 2008-11-08 in Java by Johann.

Redirects in Servlets

To perform a permanent or temporary redirect in a Servlet, set the status property of the HttpServletResponse object to either SC_MOVED_PERMANENTLY (301) or SC_MOVED_TEMPORARILY (302) and set the Location header to the target URL.

response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", "https://johannburkard.de/");

While the HttpServletResponse object already has a sendRedirect method, the specification says that it sends…

…a temporary redirect response to the client using the specified redirect location URL.

This is why I select the HTTP status code manually.

Redirects in JSPs

JSPs obviously take the same code as Servlets. Here is a sample redirection in a JSP.

<%@ page import="javax.servlet.http.*"><%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", "https://johannburkard.de/"); %>

Redirects using Refresh header

Some web analytics packages do not analyze URL parameters if the HTTP status code is not 200. In this scenario, a redirect using the Refresh header can also be used.

String target = "https://johannburkard.de";
response.setContentType("text/html");
response.setContentLength(13);
response.addHeader("Refresh",
    new StringBuilder(target.length() + 5).append("0;url=").
    append(target).toString());

ServletOutputStream out = response.getOutputStream();
out.print("<html></html>");

This code is taken from my ReDirector servlet which uses XML files for redirection targets.

Debugging Redirection

wget is the Swiss army knife of HTTP tools and I frequently use its debug mode (-d) to solve HTTP problems.

> wget -d http://127.0.0.1:8081/servlet/com.eaio.TestServlet
DEBUG output created by Wget 1.10.2 on Windows.

--10:15:54--  http://127.0.0.1:8081/servlet/com.eaio.TestServlet
           => `com.eaio.TestServlet'
Connecting to 127.0.0.1:8081... seconds 0.00, connected.
Created socket 1952.
Releasing 0x003a49a8 (new refcount 0).
Deleting unused 0x003a49a8.

---request begin---
GET /servlet/com.eaio.TestServlet HTTP/1.0
User-Agent: Wget/1.10.2
Accept: */*
Host: 127.0.0.1:8081
Connection: Keep-Alive

---request end---
HTTP request sent, awaiting response...
---response begin---
HTTP/1.1 301 Moved Permanently
Date: Sat, 08 Nov 2008 09:15:56 GMT
Server: Orion/2.0.7
Connection: Close
Content-Type: text/plain
Location: https://johannburkard.de/

---response end---

Call native methods in a DLL from Java without JNI

Posted 2007-05-27 in Java by Johann.

In this example, we will monitor a directory without continously polling it’s contents. Instead, we’ll rely on the Windows API that we access through NativeCall – that is, without JNI.

The functions

To monitor the directory, we need the following functions:

These functions are all implemented in kernel32.dll. Fortunately, this is the default DLL in NativeCall so we don’t need to specify it.

Getting started

After unpacking the NativeCall distribution, we add the JAR to the CLASSPATH and set up java.library.path to point to the directory with the NativeCall native library in it. We then initialize NativeCall by calling NativeCall.init().

Functions

We obtain references to the functions with the following code:

IntCall createFile = null;
IntCall closeHandle = null;
IntCall readDirectoryChanges = null;

int dirHandle = 0;
try {
    createFile = new IntCall("CreateFileA");
    closeHandle = new IntCall("CloseHandle");
    readDirectoryChanges = new IntCall("ReadDirectoryChangesW");
    …
}
finally {
    if (closeHandle != null) {
        if (dirHandle != 0) {
            closeHandle.executeBooleanCall(
                new Integer(dirHandle));
        }
        closeHandle.destroy();
    }
    if (readDirectoryChanges != null) {
        readDirectoryChanges.destroy();
    }
    if (createFile != null) {
        createFile.destroy();
    }
}

Calling destroy in a finally block is important to ensure that all resources are freed. If you forget this, you will leak memory.

Directory handle

The directory handle is acquired with the following code:

dirHandle = createFile.executeCall(new Object[] {
    new Integer(dirHandle),
    DESIRED_ACCESS, SHARE_MODE, null, CREATION_DISPOSITION,
    FLAGS_AND_ATTRIBUTES, null });

The constants you see are simple Integers.

Monitoring the directory

All that’s left to do now is to call the ReadDirectoryChangesW method. In this example, this is a synchronous call which will block until the directory is changed.

Holder returnedBufferLength = new Holder(0);
	
byte[] buffer = new byte[1024];
Arrays.fill(buffer, (byte) 0xff);
Holder fileNotifyInformation = new Holder(buffer);

readDirectoryChanges.executeBooleanCall(new Object[] {
    directory.getCanonicalPath(), fileNotifyInformation,
    new Integer(buffer.length), false, NOTIFY_FILTER,
    returnedBufferLength, null, null });

Get the code

Download DirectoryMonitor.java and DirectoryMonitorTest.java, the test case and start hacking.

15 comments

CORBA Packet Sniffing/Class Patching Hack

Posted 2008-12-08 in Java by Johann.

This is a nasty, ugly hack for situations where you are forced at gunpoint to deal with the abomination that is CORBA. It lets you see incoming CORBA data – without using an actual packet sniffer/network protocol analyzer.

What we will be doing is:

  1. Take the source from one JDK class
  2. modify it and
  3. place it before the actual JDK class with the -Xbootclasspath/p: switch.

In essence, this lets you patch or edit any JDK or application class, which is good for a variety of scenarios, including closed-source software.

The Class

The class to patch is com.sun.corba.se.impl.encoding.EncapsInputStream. This class is responsible for receiving the GIOP-encoded CORBA data.

The original constructor code:

    public EncapsInputStream(org.omg.CORBA.ORB orb, byte[] buf, 
                 int size, boolean littleEndian,
                 GIOPVersion version) {
        super(orb, ByteBuffer.wrap(buf), size, littleEndian,
          version, Message.CDR_ENC_VERSION,
          BufferManagerFactory.newBufferManagerRead(
                      BufferManagerFactory.GROW,
                      Message.CDR_ENC_VERSION,
                      (ORB)orb));

    wrapper = ORBUtilSystemException.get( (ORB)orb, 
        CORBALogDomains.RPC_ENCODING ) ;

        performORBVersionSpecificInit();
    }

The Modification

Modifying this class involves creating the ByteBuffer in a static method and printing the data contained in buf there. Something like this:

    private static ByteBuffer wrap(byte[] buf) {
        System.out.println(new HexDumpEncoder().encode(buf));
        return ByteBuffer.wrap(buf);
    }

    // corba/EncapsOutputStream
    // corba/ORBSingleton
    // iiop/ORB
    public EncapsInputStream(org.omg.CORBA.ORB orb, byte[] buf, 
                 int size, boolean littleEndian,
                 GIOPVersion version) {
        super(orb, wrap(buf), size, littleEndian,
          version, Message.CDR_ENC_VERSION,
          BufferManagerFactory.newBufferManagerRead(
                      BufferManagerFactory.GROW,
                      Message.CDR_ENC_VERSION,
                      (ORB)orb));

    wrapper = ORBUtilSystemException.get( (ORB)orb, 
        CORBALogDomains.RPC_ENCODING ) ;

        performORBVersionSpecificInit();
    }

The Launch

With the class patched, we need to prepend the directory or JAR it is located in to the bootstrap classpath.

>java -X
…
    -Xbootclasspath/p:<directories  ; by separated files jar zip and>
                      prepend in front of bootstrap class path

If your classes are compiled to the bin directory, -Xbootclasspath/p:bin is enough. You might need some libraries which can be appended to the bootstrap class path like so -Xbootclasspath/p:bin:lib/junit.jar:lib/wljmsclient.jar.

The Result

Each CORBA packet that your computer receives is neatly dumped to the console.

Pages

Page 1 · Page 2 · Page 3 · Page 4 · Next Page »

Subscribe

RSS 2.0, Atom or subscribe by Email.

Top Posts

  1. DynaCloud - a dynamic JavaScript tag/keyword cloud with jQuery
  2. 6 fast jQuery Tips: More basic Snippets
  3. xslt.js version 3.2 released
  4. xslt.js version 3.0 released XML XSLT now with jQuery plugin
  5. Forum Scanners - prevent forum abuse
  6. Automate JavaScript compression with YUI Compressor and /packer/

Navigation