I was helping a development group uncover the cause of a memory leak a while back, and figured I should share the finding here.
The memory leak in this case was induced by the static method "getAnonymousLogger()" on the class "java.util.logging.Logger"; although it looks like it could be caused by any logger that sets a parent in code. When an anonymous logger is created, it is created from scratch, and the root looger is set as the parent.
When a logger has its parent set in code, a weak reference is created on the parent for its list of "kids". This design allows short lived loggers to be garbage collected even though the parent maintains a reference to the logger. Great in theory, but missing a component in the current implementation. The current implementation never cleans up the weak reference objects. That is, the memory used by the Logger is freed, but the weak reference held by the parent is not. Those interested in the bug can get the JDK source code, and look at the private doSetParent(Logger) method on the Logger class.
Calling setParent or getting an anonymous logger leaks a minuscule amount of memory per invocation. In applications that run for a very short period of time (like an applet), this is probably unnoticeable. When called per invocation of a servlet in a long running j2ee container, it will eventually kill your JVM instance.
So how do you get around it? My first suggestion is to never use getAnonymousLogger unless you have an exceptionally good reason (probably involving the security manager). My second suggestion is to save a reference to the Logger object as a member field, and always reuse that reference.
Software development, Programming languages, Virtual Machines, Virtualization, and Systems Architecture.
Showing posts with label java. Show all posts
Showing posts with label java. Show all posts
Wednesday, May 27, 2009
Wednesday, January 9, 2008
What you should know about GC, but probably don't
Chaotic Java has an outstanding review of the JVM garbage collectors in two parts. The first is an introduction to mark and sweep garbage collections, and the second is a quick, mostly understandable, review of concurrent garbage collection.
In my experience in working with .Net and Java, I have found that most developers have little-to-no knowledge of the theories behind garbage collection and reference strength. I fear for the future of development if more developers don't understand the tools of their trade in greater detail. Who knows what products they might be working on, or how acceptable a restart every four minutes will be.
In my experience in working with .Net and Java, I have found that most developers have little-to-no knowledge of the theories behind garbage collection and reference strength. I fear for the future of development if more developers don't understand the tools of their trade in greater detail. Who knows what products they might be working on, or how acceptable a restart every four minutes will be.
Monday, January 7, 2008
Coconut AIO collects dust.
Coconut AIO is part of the Coconut project at Codehaus. The focus of the coconut project is highly concurrent internet services. This includes things like caching, multi-threaded IO, etc. Sadly, the AIO component of Coconut is no longer developed, and is considered discontinued. Even the Coconut website no longer references the Coconut AIO package.
One of the things I liked about Coconut AIO was that it was based around java.util.concurrent.Future objects. This provided more accessibility to junior developers since the whole model behind selector threads, content filters, and registering socket interests can be rather daunting.
Maybe the Coconut group will revisit the AIO package after they finish work on their caching services.
One of the things I liked about Coconut AIO was that it was based around java.util.concurrent.Future objects. This provided more accessibility to junior developers since the whole model behind selector threads, content filters, and registering socket interests can be rather daunting.
Maybe the Coconut group will revisit the AIO package after they finish work on their caching services.
Wednesday, December 19, 2007
Java NIO and The Grizzly
I have been working on a small side project to develop a highly scalable reporting and analysis service. Part of the design calls for all "processing" nodes to maintain persistent connections to every other "processing" node in the cloud. I knew the idea of using blocking IO and the 1:1 thread/connection model was going to be horrible for this design.
I first turned to the Java NIO packages. I always start with trying to understand the underlying technology before I start looking into libraries. While I wouldn't say that the Java NIO packages are exceptionally difficult to work with, they leave a lot to be desired in the documentation department. Even the examples and tutorials that exist on the internet appear incomplete. Very few touch on the best methods for dealing with write operations. Between writes, and fully understanding how to properly iterate over my selected key set (you have to call iterator.remove() after calling iterator.next()), I spent a week trying to get a firm grasp on what was really going on. By the end of the second week, I had created a prototype java application that listened on sockets and was playing hot potato with a serializable java object. I had acquired my basic understanding. Now ready for looking into libraries.
Grizzly is the library I am currently looking at. Getting a simple echo service up and running in Grizzly is a no brainer. The concept can be completed in under 20 lines of code. Grizzly even comes with protocol parsers and other useful interfaces that make developing your own protocol directly on-top of TCP or UDP a straightforward exercise. I haven't gotten to far down the path of implementation yet, but I will definately be using Grizzly rather than rolling my own NIO solution.
The code for the Grizzly version of a simple echoing server is below:
I also researched the following libraries: EmberIO (part of Pyrasun), Apache Mina, and Coconut AIO. I will be posting some of my experiences with these libraries later.
I first turned to the Java NIO packages. I always start with trying to understand the underlying technology before I start looking into libraries. While I wouldn't say that the Java NIO packages are exceptionally difficult to work with, they leave a lot to be desired in the documentation department. Even the examples and tutorials that exist on the internet appear incomplete. Very few touch on the best methods for dealing with write operations. Between writes, and fully understanding how to properly iterate over my selected key set (you have to call iterator.remove() after calling iterator.next()), I spent a week trying to get a firm grasp on what was really going on. By the end of the second week, I had created a prototype java application that listened on sockets and was playing hot potato with a serializable java object. I had acquired my basic understanding. Now ready for looking into libraries.
Grizzly is the library I am currently looking at. Getting a simple echo service up and running in Grizzly is a no brainer. The concept can be completed in under 20 lines of code. Grizzly even comes with protocol parsers and other useful interfaces that make developing your own protocol directly on-top of TCP or UDP a straightforward exercise. I haven't gotten to far down the path of implementation yet, but I will definately be using Grizzly rather than rolling my own NIO solution.
The code for the Grizzly version of a simple echoing server is below:
public static void main(String[] args)
throws IOException {
Controller controller = new Controller();
TCPSelectorHandler handler =
new TCPSelectorHandler();
handler.setPort(9090);
controller.setProtocolChainInstanceHandler(
new DefaultProtocolChainInstanceHandler() {
public ProtocolChain poll() {
ProtocolChain chain = protocolChains.poll();
if (chain == null) {
chain = new DefaultProtocolChain();
chain.addFilter(new ReadFilter());
chain.addFilter(new EchoFilter());
}
return chain;
}
}
);
controller.addSelectorHandler(handler);
controller.start();
}
I also researched the following libraries: EmberIO (part of Pyrasun), Apache Mina, and Coconut AIO. I will be posting some of my experiences with these libraries later.
Subscribe to:
Posts (Atom)