Garbage Collector Pitfalls
Posted 2009-03-04 in Java by Johann.
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:
CreateFileA
to create a handle to the directory.CloseHandle
to close the handle.ReadDirectoryChangesW
to monitor it for changes.
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 Integer
s.
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:
- Take the source from one JDK class
- modify it and
- 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
- DynaCloud - a dynamic JavaScript tag/keyword cloud with jQuery
- 6 fast jQuery Tips: More basic Snippets
- xslt.js version 3.2 released
- xslt.js version 3.0 released XML XSLT now with jQuery plugin
- Forum Scanners - prevent forum abuse
- Automate JavaScript compression with YUI Compressor and /packer/