Friday 22 August 2014

Profiling & jvisualvm

JVisualVm is a really good profiling tool for use with Java.  It is included in the JDK.

To use it on a local running instance then just run it.  All the VMs will appear in the application menu on the left hand side.

Remote
JVisualVM can also be used remotely.  On the machine with the VM to profile, create a policy file which contains the following

// create a policy file called all.policy
grant codebase "file:${java.home}/../lib/tools.jar" {
   permission java.security.AllPermission;

};

Then create a RMI instance on a particular local port (1099 is standard but any port can be used such as 2020)

// Start the rmiregistry

rmiregistry 1099&

And now use jstatd to populate the registry.

// Start jstatd with the policy file above and point it to the rmiregistry

jstatd -J-Djava.security.policy=all.policy -p 1099

Now start jvisualvm on a local machine and connect to port 1099 on the remote machine to view the details.

Within jvisualvm right click on 'Remote' and select 'Add remote host'.  In the hostname add the IP address of the remote machine and in 'Advanced' the port can be change if 1099 isn't used for the rmiregistry or jstatd.

It isn't possible to do everything with a remote connection that you can do with a local connection. For this reason it can be useful to run jvisualvm locally but use X11 forwarding to put the actual application on a remote machine.

Troubleshooting

Sometimes there are connection issues when trying to connect to a remove jstatd.  So check the following

Logs
Look at the jvisualvm logs which can be found in ~/.visualvm/<version>/var/log

Headless
Although jvisualvm can be run with X11 forwarding so it can be a headless environment it has dependencies on some X11 libraries so needs to have a desktop manager installed even if it isn't running. (libXext.so.6)

Firewall
Make sure that any firewall isn't blocking the RMI ports.

RMI address
Sometimes the RMI address needs to be set so try adding

    -J-Djava.rmi.server.hostname=<ip address>

IP version
It is also possible to try to force IPv4 to see if that helps,

    -J-Djava.net.preferIPv4Stack=true 


Other Tools

There are a number of other tools which are useful to ascertaining if there is a memory leak in the heap.  A heap dump can be generated using the jmap command which is part of the jdk

    ./jmap -dump:format=b,file=<filepath> <pid>

This generates a hprof format.  There is a free tool called the Memory Analyser Tool (MAT) which is based on the eclipse platform and can be used to analyse the heap file.

    http://www.eclipse.org/mat/

Wednesday 13 August 2014

@Transactional

When connecting to a database a transaction is often required.  There are a number of ways of doing this but the most common is to use Spring transactions.

pom.xml

This dependency is needed to allow transactions

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<scope>compile</scope>
</dependency>


Spring Context

In the spring configuration an entity manager is necessary (see Entity Manager blog entry)

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

<!-- Define a transaction manager so that the @TransactionConfiguration and @Transactional can be used -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

Proxy Class

The above combination will allow spring to create proxy classes which create a transaction before passing into the @Transactional method.  This means that because it is a proxy @Transactional doesn't work for any 'internal' call within the your class.  Eg even if a method is public if it is called from within the same class it won't pass through the proxy and therefore won't have a transaction.
If this type of behaviour is required then the transactions can be wired using AOP and the transaction code is created at compile time rather than a runtime proxy.

Exception Handling

Normal exceptions can be caught using the normal try - catch but if the database isn't there at all then there is an exception generated in the proxy before the method code is called.  The exception is a 
    org.springframework.transaction.CannotCreateTransactionException

To catch the exception within the same method as the actual database errors the transaction can be created a different way.

Programmatic Transactions

A programmatic transaction can be created using the TransactionTemplate in which case the TransactionException (CannotCreateTransactionException) can be caught in the same place.

    try
    {
        transactionTemplate.execute(new TransactionCallbackWithoutResult()
        {
            @Override
            protected void doInTransactionWithoutResult(final TransactionStatus status)
            {
                 // Do something to the database here
            }
        });
    }
    catch (PersistenceException | TransactionException e)
    {
        LOG.error("Database Error", e);
    }

There is also a TransactionCallback() which returns the object from the database whereas the one above doesn't do that.

The transactionTemplate can be created in spring configuration,

    <property name="transactionTemplate">
        <bean class="org.springframework.transaction.support.TransactionTemplate">
            <constructor-arg ref="transactionManager" />
</bean>
    </property>