3.18.2014

This post is to inform you that Java 8 has been officially released by Oracle. You can download the official release here.

In a nutshell:

Lambda expressions: a new language feature that enables you to treat functionality as a method argument, or code as data.

Other significant enhancements and changes to the Java language and standard libraries including default methods, the new java.util.stream package, and the Date-Time API.

Compact Profiles contain predefined subsets of the Java SE platform and enable applications that do not require the entire Platform to be deployed and run on small devices.

Security enhancements include updates to the Java Cryptography Architecture; limited doPrivileged, a mechanism that enables code to assert a subset of its privileges; SSL/TLS Server Name Indication (SNI) Extension; and keystore enhancements.

JavaFX documentation has been updated for this release.

A new JavaScript engine, Nashorn, is included in JDK 8.

Java Mission Control 5.3 is included in JDK 8.

Decommission of the JVM Permanent Generation space and replaced by the Metaspace.

I will publish more articles in the upcoming weeks, including tutorials on Java Mission Control 5.3 which is now part of the JDK 8.

In the meantime, I suggest that you revisit my original article on the replacement of the HotSpot PermGen space by the Metaspace. I will publish the part 2 in the upcoming weeks.

3.13.2014

Most Java developers
are familiar with the infamous and very common java.lang.ClassNotFoundException.
While the sources of this problem are generally well understood (missing classes/libraries
in classpath, class loader delegation problems etc.), the impact to the overall
JVM and performance is often unknown. This situation can lead to significant
impacts to your application response time and scalability.

Large Java
EE enterprise systems with multiple applications deployed are the most exposed
to this type of problem due to the large number of different application
classloaders active at runtime. This increases the risk of facing “undetected”
ClassNotFoundException unless a clear business impact is identified and close
log monitoring is implemented, results: on-going performance impact along with possible
JVM class loading IO and Thread lock contention.

The
following article and sample programs will demonstrate that any occurrence of
ClassNotFoundException found from your client production systems should be
taken very seriously and addressed promptly.

Java class loading: the missing link for
optimal performance

Proper
understanding of this performance problem starts with proper knowledge of the
Java class loading model. ClassNotFoundException essentially means a failure of
the JVM to locate and/or load a particular Java class such as:

The Class.forName() method

The ClassLoader.findSystemClass() method

The ClassLoader.loadClass() method

While
class loading of your application Java classes should occur only once in the
JVM life-cycle (or through dynamic re-deploy functions), some applications also
rely on dynamic class loading operations.

Regardless,
repetitive valid and “failing” class loading operations can be quite intrusive,
especially when the loading process is attempted by the default JDK
java.lang.ClassLoader itself. Indeed, the default JDK 1.7+ behaviour, due to backward
compatibility, will allow only one class to be loaded at the time, unless the
class loader is tagged as “parallel capable”. Please keep in mind the even if
the synchronization is done at the Class level only, a repetitive class loading
failure against the same class name is still going to trigger thread lock
contention depending of the Java thread concurrency level you are dealing with.
The situation was much worst back with JDK 1.6 with synchronization done systematically
at the class loader instance level.

For this
reason, Java EE containers such as JBoss WildFly 8
are using their own internal concurrent
class loaders for the loading of your application classes. These class loaders implements
locking at a finer level of granularity, thus allowing loading different
classes from the same instance of the class loader concurrently. This is also
aligned with the latest JDK 1.7+ improvement introducing the support for Multithreaded
Custom Class Loaders which also help prevent certain class loader deadlock
scenarios.

That being
said, class loading of system level classes such as java.* and Java EE
container modules still fall back on the default JDK ClassLoader. This means
that repetitive class loading failure for the same class name e.g.
ClassNotFoundException can still trigger severe thread lock contention. This is
precisely what we will replicate and demonstrate for the rest of the article.

Thread lock contention - problem replication

In order
to recreate and simulate this problem, we created a simple application as per
below specifications:

A JAX-RS (REST) Web
Service executing Class.forName() against a dummy Class name “located”
from the system package level:

The simulation
essentially executes concurrently with 20
threads the JAX-RS Web service. Each invocation generates a ClassNotFoundException.
The logging was fully disabled in order to reduce impact on IO and focus on the
class loading contention only.

Now let’s look at the results from JVisualVM
from our 30-60 seconds run. We can clearly see a lot of BLOCKED threads waiting
to acquire a lock on an Object monitor.

Analysis of
the JVM thread dump is clearly exposing the problem: Thread lock contention. We
can see from the execution stack trace that JBoss delegates the loading of the
class to the JDK ClassLoader…why? This is because our wrong Java class name is
detected to be part of the system class path e.g. java.*. In this situation,
JBoss will delegate the loading to the system class loader, triggering
systematic synchronization for that particular class name and waiters from the
other threads waiting to acquire a lock to load the same Class name.

at
org.jboss.as.server.deployment.module.VFSResourceLoader$2.run(VFSResourceLoader.java:127)

at
org.jboss.as.server.deployment.module.VFSResourceLoader$2.run(VFSResourceLoader.java:124)

at
java.security.AccessController.doPrivileged(Native Method)

at
org.jboss.as.server.deployment.module.VFSResourceLoader.getClassSpec(VFSResourceLoader.java:124)

at
org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:252)

at
org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:76)

at org.jboss.modules.Module.loadModuleClass(Module.java:526)

at
org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:189) // JBoss now
fully responsible to load the class

at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:444)
// Unchecked since using JDK 1.7 e.g. tagged as “safe”
JDK

at
org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:432)

at
org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:374)

at
org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:119)

at
java.lang.Class.forName0(Native Method)

at
java.lang.Class.forName(Class.java:186)

at
org.jboss.tools.examples.rest.MemberResourceRESTService.AppCLFailure(MemberResourceRESTService.java:196)

at
org.jboss.tools.examples.rest.MemberResourceRESTService$Proxy$_$$_WeldClientProxy.AppCLFailure(Unknown
Source)

at
sun.reflect.GeneratedMethodAccessor60.invoke(Unknown Source)

……………….

The above
execution stack trace is quite revealing:

Since the Java class name was not detected to be
part of the Java system package, no ClassLoader delegation was performed,
thus no synchronization.

Since JBoss considers JDK 1.7+ as a “safe” JDK, the ConcurrentClassLoader
.performLoadClassUnchecked() method was used, not triggering any
Object monitor lock.

No synchronization means no Thread lock contention
triggered as a result of the non-stop ClassNotFoundException error.

It is
still important to note that while JBoss is doing a great job at preventing
Thread lock contention in this scenario, the repetitive class
loading attempt will still degrade the performance to a certain degree due to
IO overhead associated with excessive JAR file search operations, again
re-enforcing the need to take immediate corrective actions.

Final words

I hope
that you enjoyed this article and have nowa better understanding of potential
performance impacts due to excessive class loading operations. While JDK 1.7 and
modern Java EE containers brought great improvements on class loader related issues
such as deadlocks and thread lock contention, potential problematic scenarios
still remain. For this reason, I highly recommend that you closely monitor your
application behaviour, logs and ensure that class loader related errors such as java.lang.ClassNotFoundException and java.lang.NoClassDefFoundError are aggressively corrected.