Java Reference
In-Depth Information
[GC 4416K->318K(15872K), 0.0066670 secs]
[GC 926K->327K(15872K), 0.0040134 secs]
[Full GC 327K->327K(15872K), 0.2674688 secs]
Bundle: org.foo.shell.tty started with bundle id 3
->
Tr y u p d a t i n g t h e l e a k y b u n d l e :
-> update 1
Here, 1 is the ID of the leaky bundle, as reported by the bundles command. You
should see the heap expand each time you call update :
[GC 17857K->16753K(32324K), 0.0376856 secs]
[Full GC 16753K->16750K(32324K), 0.0329633 secs]
If you continue to update the bundle, you'll eventually get an OutOfMemoryError :
org.osgi.framework.BundleException:
Activator start error in bundle org.foo.leaky [1].
...
Caused by: java.lang.OutOfMemoryError: Java heap space
...
Unable to execute: update 1
Let's try to analyze this memory leak. Restart the framework with heap dumps enabled:
$ java -XX:+HeapDumpOnOutOfMemoryError -jar launcher.jar bundles
Repeatedly update the leaky bundle until the OutOfMemoryError occurs:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid1916.hprof ...
Heap dump file created [238744986 bytes in 16.578 secs]
You should now have a heap-dump file in your current working directory. Plenty of
open-source tools work with heap dumps; in this case, you'll use the Eclipse Memory
Analyzer ( MAT , http://eclipse.org/mat/ ). This tool provides a graphical view of the
heap and several useful reports to quickly identify potential leaks. Let's see how it
copes with an OSG i application. Figure 8.14 shows the leak suspect report for the cap-
tured heap dump.
Notice how it correctly identifies the ThreadLocal as the root of the leak. But can it
tell you what application code was responsible? To find out, click the Details link at
the bottom. Doing so opens a detailed page about the ThreadLocal , including the var-
ious thread stacks that created the instances (see figure 8.15). It clearly shows the bun-
dle activator start() method is the one responsible for creating all these instances.
With your knowledge of the OSG i lifecycle, you can infer that the problem is in the
activator stop() method.
To solve this leak, all you need to do is go back to the bundle activator and add a
call to remove() the ThreadLocal in the stop() method. This forces the underlying
data object to be cleared and means the bundle's class loader can be collected on
each update/refresh. You should now be able to continually update the bundle with-
out incurring an OutOfMemoryError .
 
Search WWH ::




Custom Search