About Stefan Reuter

Google+ | Twitter

ClassLoader Leaks by Oracle

I recently had trouble with a web application deployed on Tomcat that leaked its ClassLoader every time it was redeployed resulting in OutOfMemoryErrors after a few redeployments. This is quite nasty if you plan to do continuous deployment and don’t want to restart the servlet container with each deployment.

Recent versions of Tomcat include some code that makes you aware of problems when you undeploy the application:

SEVERE: The web application [] registered the JDBC driver [oracle.jdbc.OracleDriver] but failed to unregister it when the web application was stopped.
 To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
SEVERE: The web application [] appears to have started a thread named [Thread-14] but has failed to stop it. This is very likely to create a memory leak.
SEVERE: The web application [] appears to have started a thread named [Thread-15] but has failed to stop it. This is very likely to create a memory leak.
SEVERE: The web application [] appears to have started a thread named [Thread-16] but has failed to stop it. This is very likely to create a memory leak.
SEVERE: The web application [] appears to have started a thread named [Thread-17] but has failed to stop it. This is very likely to create a memory leak.
SEVERE: The web application [] appears to have started a thread named [Thread-18] but has failed to stop it. This is very likely to create a memory leak.

As you can see Tomcat managed to unregister the JDBC driver that the application had failed to unregister but could do nothing regarding the threads that had been started but not stopped.

I ran the application with YourKit attached to check that the WebappClassLoader had actually leaked and to see what those threads were that prevented it from being garbage collected. The “Paths from GC Roots” view in YourKit is well suited for this:

ONS Leaking Threads

As you can see there are four threads from ONS that prevent the ClassLoader from being garbage collected: oracle.ons.SenderThreads and oracle.ons.ReceiverThreads.

I wrote a small ServletContextListener that shuts down ONS to get rid of them. After that I noticed that Oracle registered a OracleDiagnosabilityMBean that I had to unregister. Finally I made sure the JDBC drivers that the application had registered were properly unregistered from DriverManager.

With those changes in place the application undeployed well and was fully garbage collected.

Here is the code:

import oracle.ons.ONS;
import oracle.ons.SenderThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

public class CleanUpListener implements ServletContextListener {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // do nothing
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        shutdownOns();
        deregisterJdbcDrivers();
    }

    @SuppressWarnings("unchecked")
    private void shutdownOns() {
        logger.info("Shutting down ONS");
        final Method getRunningONS = ReflectionUtils.findMethod(ONS.class, "getRunningONS");
        final Method shutdown = ReflectionUtils.findMethod(ONS.class, "shutdown");
        ReflectionUtils.makeAccessible(getRunningONS);
        ReflectionUtils.makeAccessible(shutdown);
        final ONS ons = (ONS) ReflectionUtils.invokeMethod(getRunningONS, null);
        if (ons == null) {
            return;
        }
        
        ReflectionUtils.invokeMethod(shutdown, ons);

        final Field senders = ReflectionUtils.findField(ONS.class, "senders");
        ReflectionUtils.makeAccessible(senders);
        final List<SenderThread> senderThreads = (List<SenderThread>) ReflectionUtils.getField(senders, ons);
        if (senderThreads == null) {
            return;
        }
        
        final Method stopThread = ReflectionUtils.findMethod(SenderThread.class, "stopThread");
        ReflectionUtils.makeAccessible(stopThread);
        for (SenderThread senderThread : senderThreads) {
            ReflectionUtils.invokeMethod(stopThread, senderThread);
        }
    }
    
    private void deregisterJdbcDrivers() {
        logger.info("Deregistering JDBC Drivers");
        final Enumeration<Driver> driverEnumeration = DriverManager.getDrivers();
        final List<Driver> drivers = new ArrayList<Driver>();
        while (driverEnumeration.hasMoreElements()) {
            drivers.add(driverEnumeration.nextElement());
        }

        for (Driver driver : drivers) {
            if (driver.getClass().getClassLoader() != getClass().getClassLoader()) {
                logger.debug("Not deregistering {} as it does not originate from this webapp", driver.getClass().getName());
                continue;
            }
            try {
                DriverManager.deregisterDriver(driver);
                logger.debug("Deregistered JDBC driver '{}'", driver.getClass().getName());
                if ("oracle.jdbc.OracleDriver".equals(driver.getClass().getName())) {
                    deregisterOracleDiagnosabilityMBean();
                }
            } catch (Throwable e) {
                logger.error("Deregistration error", e);
            }
        }
    }

    private void deregisterOracleDiagnosabilityMBean() {
        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        try {
            final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            final Hashtable<String, String> keys = new Hashtable<String, String>();
            keys.put("type", "diagnosability");
            keys.put("name", cl.getClass().getName() + "@" + Integer.toHexString(cl.hashCode()).toLowerCase());
            mbs.unregisterMBean(new ObjectName("com.oracle.jdbc", keys));
            logger.info("Deregistered OracleDiagnosabilityMBean");
        } catch (javax.management.InstanceNotFoundException e) {
            logger.debug("Oracle OracleDiagnosabilityMBean not found", e);
        } catch (Throwable e) {
            logger.error("Oracle JMX unregistration error", e);
        }
    }
}

My First Steps with Arch Linux


I’ve been using Ubuntu for quite some time now on my desktop and for my servers. It works well and I like the Debian style apt package manager. However I am less happy with the more recent developments. Ubuntu packages differ more and more from the upstream packages and with their focus on Unity I started wondering whether there is a better fit for my Linux needs.

For my new T420s I decided to give Arch Linux a try after I had a short look at Mint, Debian, Fedora and openSUSE.

The Arch Way makes Arch different as it values simplicity and takes an elegant, minimalist approach. The core installation installs just what you absolutely need so you are greeted by a friendly command line when it’s done. After that you can easily install a graphical environment including Gnome 3 with or without shell, KDE and Xfce along with whatever packages you need. Software patches are kept to a minimum so most Arch packages are identical or at least very close to their upstream counterparts. The difference is similar to the “Google experience” of a Nexus One or Nexus S and the modified Android versions sold by the manufacturers. New versions of upstream software end up in Arch within days.

Arch is a rolling release distro that allows for a one-time installation and perpetual software upgrades. There is no need to reinstall or upgrade the system from one version to the next. Everything in Arch is bleeding edge.

Installation on my T420s did not work as smooth as Ubuntu. The latest official installation ISO is from May 2010 and does not support the network card of the T420s. There are newer testing versions but they have issues setting up full disk encryption. So I went with the official ISO and installed the updates via WLAN which worked well.

If you come from the Debian world you are used to apt for package management. Arch comes with pacman which is similar but a lot faster. Bringing your system up to date just means you have to run pacman -Syu instead of apt-get update && apt-get upgrade. After that you have the latest kernel (2.6.39 as of now). I Installed a few additional packages including XF86, Gnome, Chromium, Thunderbird and Libre Office and had a nice working system. Sound and the Touchpad including scrolling worked out of the box. For the network I decided to use Gnome’s NetworkManager so I installed network-manager-applet and modemmanager and got an easy to manage network setup with support for wired lan, WLAN and wireless broadband. My Ericsson F5521gw was recognized automatically and UMTS worked right away.

The Arch Wiki is a great resource and the home of the excellent documentation of Arch. For each part of the system you have multiple options to choose from and they are well explained.

Up to now I am really happy with Arch.

A few notes:

To setup focus follows mouse in Gnome run

gconf-editor /apps/metacity/general/focus_mode

and change the value from click to sloppy.

To make the massive Gnome 3 title bars a bit less high run

sed -i \
 "/title_vertical_pad/s/value=\"[0-9]\{1,2\}\"/value=\"0\"/g" \
 /usr/share/themes/Adwaita/metacity-1/metacity-theme-3.xml

Posted in Uncategorized | Tagged ,

From Subversion to Git

Yesterday I’ve converted the Asterisk-Java repositories from Subversion to git. It’s rather easy when you use git-svn:

sudo apt-get install git-svn
git svn clone file:///var/lib/svn/repos/asterisk-java \
  --no-metadata -A authors.txt \
  -t tags -b branches -T trunk asterisk-java

The authors file maps the users in Subversion to the git users. While Subversion usually uses a short username, git uses the full name with email address as a globally unique identifier for users. My authors file looked like this:

srt = Stefan Reuter <stefan.reuter@example.com>
root = Stefan Reuter <stefan.reuter@example.com>

As I had direct filesystem access to the Subversion repositories I chose to use the file protocol instead of HTTP so it was much faster. The --no-metadata option tells git-svn not to include the orignal Subversion revision number in every commit. This removes clutter from the history.

Finally git-svn creates branches for all tags in Subversion which is a bit nasty. So I converted them to git tags:

cd asterisk-java
for tag in `git branch -r | grep '^  tags' | sed 's,  tags/,,'`
do
  echo Converting Tag $tag
  git tag $tag tags/$tag
  git branch -r -d tags/$tag
done

There it is a nice git repository containing the full history. I only had to push it to github to make it available to everybody who is interested:

git remote add origin git@github.com:srt/asterisk-java.git
git push origin master
git push --tags

Spring Framework Security Vulnerability Part 2

I’ve already talked about CVE-2010-1622 and what SpringSource could have done better when dealing with this security issue.

Today I want to focus on what you as a developer or system administrator can learn from the bug.

What can developers learn from CVE-2010-1622?

The exploit requires manipulating the class loader property so that it will download code from an external site. So you can prevent the attack by disallowing modifications of the class loader and by disallowing your application to download and run code from external sites.

Be explicit! Explicitly allow binding of certain properties. This prevents the exploit from working as there is no valid use case that requires access to the class property. Explicitly whitelisting properties also makes sure users cannot change the id of the object bound to a form or altering data that is managed internally like “date of creation” or “last modified by” properties.

To prevent code from external sites being downloaded and executed you can make sure your applications behaves well when run with a security manager. While this is a common concept used for client side code like applets it is far less common for server side applications. Tomcat usually works well with a security manager though it is not enabled by default. Making sure you appplications works with a security manager is also a variant of being explicit: You explicitly grant certain privileges to your code bases and disallow everything else that might be abused by attackers.

What can system administrators learn from CVE-2010-1622?

Your applications should run in a demilitarized zone where they are unable to access the internet or your intranet. If you really need access to external resources use a proxy server and white list the URLs your application needs to contact. Doing so prevents attackers from making your application download external code.

If your applications are built in a way that they work with a security manager use it! For Tomcat there is a short Howto available.

Spring Framework Security Vulnerability Part 1


Spring Source recently published CVE-2010-1622. The advisory describes a vulnerability that affects Spring Framework prior to 3.0.3 and allows attackers to execute arbitrary code.

What could SpringSource have done better?

When Spring Source announced the release of 3.0.3 they reported to have fixed “more than a hundred minor issues” — no indication of the security fix. This could be understandable as they have released the fix 2 days prior to publishing the advisory. I do not understand why they did not announce it later however. The advisory was published as silently as possible although the vulnerability is rated critical, can be exploited remotely and probably affects a large number of applications.

I would have preferred receiving the security advisory through the usual channels used for announcements in addition to the security team page.

Having a look at cve.mitre.org reveals another interesting fact. The CVE id was assigned on April, 29th. That is almost 2 months before the advisory was published. The bug was fixed on May, 27th.

Why does it take more than 4 weeks for a 3 line fix? Why does it take almost 3 additional weeks after the fix to announce the vulnerability?

I would have preferred a priority fix as soon as possible after discovery and a release following short time after that.

Finally SpringSource dicided not to provide a fixed release for dm Server, a product based on Spring Framework, which is also vulnerable. Users are advised to manually patch it instead. SpringSource also continues to provide the vulnerable dm Server 2.0.2 for download without any warning.

I would have preferred to receive a fixed release of dm Server instead of seeing SpringSource continue to ship products containing known security issues.

What can you learn from CVE-2010-1622?

I will follow up with the lessons learned for application developers and system administrators in the next days. Stay tuned.

There is also an interesting analysis of the issue at blog.o0o.nu.

Code Style: Braces, Indentation and Line Length


We’ve recently revisted our Java Coding Conventions. For several years we are now using a style based on the excellent book The Elements of Java Style by RougeWave. It follows the Sun Code Style in many aspects and adds a lot of reasoning.

Our Code Style differs mainly in two aspects:

  • We place curly braces on new lines
  • We use a maximum line length of 130 characters

I am well aware that there are religious opinions regarding those questions but after reconsidering our style we came to the conclusion that both differences actually make sense.

Lining up curly braces vertically (called Allman or ANSI style) makes it easy to check that the braces match. The indented code is clearly set apart from the containing statement by lines that are almost completely whitespace which makes the code easier to read. In contrast to K&R style it consumes more space but today’s screens are well capable to show more than the ancient 24 lines.

Good:

if (condition)
{
    body;
}

Bad:

if (condition) {
    body;
}

The reason to limit the line length to 80 characters comes from the limitation of old printers that usually printed 80 characters per line. We seldomly print code on paper and modern printers are well capable to print at other resolutions. Limiting us to to 80 characters would waste a lot of screen space as with a decent screen size showing 130 characters still leaves enough place for the IDE to show up additional frames including outlines and project files left and right to the code.

What we learned: Use the mainstream conventions by default. Challenge them and check if the underlying assumptions hold true in your environment. Only derive if there is enough benefit to justify the change.

Java Applications on Privileged Ports

I am running most of my Java applications with Java Service Wrapper on Ubuntu. Most of these applications can run on unprivileged ports above 1024, e.g. Tomcats running behind an Apache http reverse proxy or the Openfire XMPP server that uses ports above 1024 by default. However there are exceptions like the LDAP server ApacheDS or Tomcats that do not require the features of httpd in front of them.

If you want to run Java applications on privileged ports below 1024 there are several options you can choose from:

To use authbind follow these steps:

Step 1: Install and configure authbind

Install authbind from the Ubuntu repository:

# aptitude install authbind

For each port your application should be able to bind to create a file in /etc/authbind/byport and make in executable by the user that runs your application. For ApacheDS I did the following:

# cd /etc/authbind/byport
# touch 389 636
# chown apacheds:apacheds 389 636
# chmod 700 389 636

This results in the following files:

# ls -l /etc/authbind/byport/
total 0
-rwx------ 1 apacheds apacheds 0 2010-05-04 21:24 389
-rwx------ 1 apacheds apacheds 0 2010-05-04 21:24 636

More information on access control is available in authbind (1).

Step 2: Update wrapper.conf

Authbind works by overloading the bind function in libc. This is done by setting the environment variable LD_PRELOAD. If you are using Java Service Wrapper the easiest way to do this is to add the following line to your wrapper.conf:

set.LD_PRELOAD=/usr/lib/authbind/libauthbind.so.1

As authbind only supports IPv4 you must prevent your application from binding to the IPv6 port as well. This can be achieved by setting the system property java.net.preferIPv4Stack in wrapper.conf:

wrapper.java.additional.1=-Djava.net.preferIPv4Stack=true

That’s it!

This approach works with any Java application and is not limited to ApacheDS. Have a look at A Better Tomcat for Ubuntu and Debian by MuleSource to see how they are using authbind without Java Service Wrapper to make Tomcat run on standard HTTP ports.

Book Review: Modular Java


Modular Java by Craig Walls is a book on building modular Java applications on OSGi platforms.

Published in the Pragmatic Bookshelf series it keeps up to the standards of that great series by presenting content that matters in a format that makes you try it out immediately.

OSGi’s value proposition is to keep complexity in software products manageable. It keeps modules isolated from each other and encourages loose coupling through publishing and consuming services. You can think of OSGi as an incarnation of service oriented archietcure (SOA) within the Java Virtual Machine. OSGi has its roots in the embedded systems environment and became popular for desktop applications with Eclipse using it as their core infrastructure. From embedded to desktop OSGi is currently coming to the server side.

Craig’s book introduces the basics of OSGi, shows how it isolates modules by its unique approach to classpath handling and gives you an overview of the concept of OSGi services. One easy to follow example application is used consistently throughout the book to show the various aspects.

Most of the time the book uses Equinox as runtime but Felix and Knopflerfish are also mentioned. For building bundles Modular Java makes use of Pax especially Pax Construct. It does not mention Bundlor, Bnd or Tycho in depth. Especially the Maven based Tycho stack sounds really promising so it’s unfortunate that it isn’t covered. I guess however this is just an attribution to the current speed of development in the OSGi tooling space.

Spring Dynamic Modules are an attempt to bring the principles of Spring Framework to OSGi. In the spirit of Spring Framework Dynamic Modules (DM) build on proven solutions (OSGi in this case) and make them easier to use. They eliminate a lot of boilerplate code that is normally require to handle OSGi services that may appear and disappear at any time. Spring-DM also provides integration with Spring Application Contexts and has support for web applications through an extender. Spring-DM is covered really well by the book. An appendix describes the new OSGi Blueprint Services that are an attempt to standardize the ideas of Spring-DM. Spring’s new dm Server is not covered.

The book focuses on the core concepts and shows the benefits of using OSGi for application development. The target audience are experienced Java developers. It is very well written, easy and fun to read and serves as a great introduction. I recommend the book to Java developers who consider making use of OSGi in future projects.

Code Style: Final Arguments

Java allows you to make arguments final by declaring them as final in the argument list of the method declaration:

public void doSomething(final String foo)
{
  ...
}

This means that inside the method you cannot change what the argument reference points to, i.e. it prevents you from doing things like this:

  foo = "bar";

It is bad style to change the reference an argument points to. You should treat all arguments as if they were marked final. It would have even been a good idea to make this a language feature and have Java treat all arguments as final by default.

However does this justify to declare all arguments as final? Some people suggest this though I haven’t seen this in the wild very often.

The pros:

  • enforces not changing the reference an argument points to

    The cons:

    • makes method signatures longer and harder to read
    • takes longer to write, being lazy is a virtue

    There is one thing to note: Changing the reference the argument points to does not actually change the value of the caller’s variable passed to the method:

    public void testDoSomething()
    {
      String foo = "foo";
      doSomething(foo);
      System.out.println(foo); // still prints "foo"
    }
    
    public void doSomething(String foo)
    {
      foo = "bar";
    }
    

    However if you pass an object that is not immutable and you change the state inside the called method you actually do change the caller’s data. This is nothing a final modifier can prevent you from doing though it may be a source of trouble if not properly stated in the contract of the method.

    So to sum it up: You should not change the reference an argument points to as it causes confusion. You can prevent this by adding the final modifer. Doing so however clutters your code and thus shouldn’t be done (except when needed to use the argument in an inner class). Pay attention to not change the state of an object passed to a method if that’s not part of the method’s contract.

    The same applies to some extend to final local variables. Use them where they make your code easier to understand but not everywhere you could. If you are a fan of final have a look at Scala‘s val keyword.

SSO for RoundCube Webmail with Atlassian Crowd

Atlassian Crowd is a single sign-on and identity management tool by Atlassian that integrates well with their suite of software engineering and collaboration tools like JIRA, Confluence and Crucible. It offers a SOAP API that allows integration into arbitrary third-party systems. Integrating a webmail system with Crowd is quite easy. I’ve choosen RoundCube Webmail 0.2.2 as an example. RoundCube is based on PHP and has a nice and clean user interface and a well-written code base.

Step 1: Basic Integration

There is a PHP integration library that can be used as a starting point. It provides the methods for SSO but lacks the convenience of Crowd’s HttpAuthenticator. Implementing a simple PHP version of the HttpAuthenticator was the first step. My implementation uses APC to store the application token and validates every request with Crowd.

Step 2: Dovecot Masteruser

While the original version of RoundCube uses the user’s username and password to connect to the IMAP store that’s no longer possible with the crowdified version as it doesn’t have access to the user’s password. One solution is to use dovecot’s masteruser feature. With that configuration in place RoundCube can access the user’s mailbox by using its own password instead of the user’s password.

Step 3: Configuration

That’s it. Quite simple. If you like you can have a look at my patch. Check config/main.inc.php and provide the username and password of your dovecot masteruser as well as the application name, credential and service URL for Crowd.