Donnerstag, 27. Oktober 2016

Generational disparity in garbage collection

For the last year, I have been helping the startup Instana to create a Java agent that traces executions within a Java application. This execution data is collected and jointed to generate traces of user requests as well as the resulting communication between services within the system owner’s hemisphere. This way, unstructured communication can be visualized what significantly simplifies the operation of a distributed system that is composed of multiple interacting services.

In order to generate these traces, the Java agent rewrites all code that reads an external request or initiates one. Obviously, these entries and exits into or out of a system need to be recorded and additionally, meta data is exchanged to identify a request uniquely across systems. For example, when tracing HTTP requests, the agent adds a header containing a unique id which is then recorded by the receiving server as a proof of a request’s origin. Broadly speaking, it is similar to what Zipkin is modeling, but without requiring users to change their code.

In the most simple scenario, such tracing is straightforward to implement. Thanks to my library Byte Buddy which does the heavy lifting, all injected code is written in plain old Java and then copied to the relevant methods at runtime using the Java instrumentation API. For example, when instrumenting a servlet, we know that an entry to a JVM is made whenever the service method is invoked. We also know that the entry is completed when this very same method exits. Therefore, it suffices to add some code to the beginning and the end of the method to record any such entry into a VM process. And it has been the majority of my job to plow through the many Java libraries and frameworks to add support for their ways of communication. From Akka to Zookeeper, over the last year I have hello-worlded my way through the entire Java ecosystem; I even got to write EJBs for all the servers! And I had to make sense of Sun’s CORBA implementation. (Spoiler: There is no sense.)

Things do however quickly become more difficult when tracing asynchronous executions. If a request is received by one thread but is answered from within another thread, it does no longer suffice to only trace entries and exits. Therefore, our agent needs to also track all context switches in concurrent systems made via thread pools, fork join tasks or custom concurrency frameworks. And the same way that debugging asynchronous execution is difficult, this is quite a bit of work for us too. I think that I spend as much time dealing with concurrency as I do recording entries and exits.

The impact on garbage collection


But how does all this impact garbage collection? When implementing a performance monitor, one is facing a trade-off between interpreting the work of a Virtual Machine and causing work for this machine by doing so. While the majority of processing is done in the monitor back-end to which the agent reports its data, we have to do a minimum within the Java process that we share with the monitored application. And you can already guess it: by allocating objects, we inevitably have an impact on the VM’s garbage collection. Fortunately, modern garbage collection algorithms are doing excellent work and by mostly avoiding object allocation and by adaptively sampling our tracing efforts, the effect of our code changes is negligible for the vast majority of users. Ideally, we only burn a few unused processor cycles to do our work. As a matter of fact, very few applications do use their full processing potential and we are happy with grabbing a small portion of this excess.

Writing a garbage collection-friendly application is typically not too difficult. It is obvious that the easiest way of avoiding garbage is to avoid object allocation altogether. However, object allocation in itself isn’t too bad either. Allocating memory is a rather cheap operation and as any processor owns its own allocation buffer - a so-called TLAB - we do not impose an unnecessary synchronization when allocating only a bit of memory from our threads. If an object only lives in the scope of a method, the JVM can even erase the object allocation altogether as if the fields of the objects were put onto the stack directly. But even without this escape-analysis, short-lived objects are captured by a special garbage collection circle called the young generation collection that is processed quite efficiently. To be honest, this is where most of my objects end up as I often value code readability over the small improvements that escape analysis offers. Currently, escape analysis quickly hits its boundary. Yet, I hope for future HotSpots to improve to get the best of both worlds even without changing my code. Fingers crossed!

When writing Java programs, I do not typically think about the impact on garbage collection but the above guidelines tend to manifest in my code. For the majority of our agent, this has been working very well. We are running a whole bunch of example applications and integration tests to assure a good behavior of our agent and I also keep an eye on the GC when running examples. In our modern times, using tools like flight recorder and JIT watch, performance analysis has become quite approachable.

The relativity of short-lived


With an early version of our agent, I one day noticed an application to trigger tenured collection cycles that it did not trigger without it. As a consequence, collection pauses increased by a multitude. The objects that ended up in the tenured collection were however only objects of the monitored application itself. But since our agent runs mostly isolated from the application threads and at first, this did at first not make sense to me.

When digging deeper, I found that our analysis of user objects triggered some additional escapes of objects but the impact was minimal. The application did already produce a fair amount of objects, mostly by using NIO and by using fork join pools. One thing that the latter frameworks have in common is that they rely on the allocation of many short lived objects. For example, a fork-join task often splits itself into multiple subtasks which repeat this procedure until each task’s payload is small enough to be computed directly. Every such task is represented by a single, stateful object. An active fork join pool can spawn millions of such objects every minute. But since the tasks compute fast, the representing object is eligible for collection quickly and therefore captured by the young collector.

So how did these objects end up in the tenured collection all of a sudden? At this time, I was prototyping a new stitching instrumentation to track context switches between such fork join tasks. Following the path of a fork join tasks is not trivial. Each worker thread of a fork join pool applies work stealing and might grab tasks out of the queue of any other task. Also, tasks might provide a feedback to their parent task on completion. As a consequence, tracing the expansion and interaction of tasks is a rather complex process, also because of the existence of so-called continuation threads where a single task might bounce jobs to hundreds of threads within only a few milliseconds. I came up with a rather elegant solution which relied on the allocation of many short-lived objects which were allocated in bursts whenever backtracking a task to its origin. It turned out that these bursts triggered quite a few young collections themselves.

And this is what I did not consider: each young generation collection increases the age of any object that is not eligible for garbage collection at this point. An object does not age by time but by the amount of young collections triggered. This is not true for all collection algorithms but for many of them such as for all default collectors of HotSpot. And by triggering so many collections, the agent threads “prematurely matured” objects of the monitored application despite those objects being unrelated to the agent’s objects. In a way, running the agent “prematurely matured” the target application’s object.

Getting around the problem


I did at first not know how to solve this. In the end, there is no way of telling a garbage collector to treat “your objects” separately. As long as the agent threads were allocating shorter-lived objects at a faster rate than the host process, it would spoil the original objects into the tenured collection causing an increase of garbage collection pauses. In order to avoid this, I therefore started to pool the objects I was using. By pooling, I quickly matured my own objects into the tenured collection and the garbage collection behavior returned to its normal state. Traditionally, pooling was used to avoid the costs of allocation which became cheap in our days. I rediscovered it to erase the impact of our “foreign process” onto garbage collection for the cost of a few kilobytes of memory.

Our tracer is already pooling objects in other places. For example, we represent entries and exits as thread local values that contain a bunch of primitive values that we mutate without allocating a single object. And while such mutable, often procedural and object pooling programming is no longer fashionable, it turns out to be very performance friendly. In the end, mutating bits is closer to what a processor is actually doing. And by using preallocated arrays of a fixed size instead of immutable collections, we save us quite a few round-trips to memory while also preserving our state to be contained in only a few cache lines.

 

Is this a “real world” problem?


You might think that this is a rather specific problem that most people do not need to worry about. But as a matter of fact, the problem that I describe applies to a large number of Java applications. For example, within application containers, we typically deploy multiple applications in a single Java process. Just as in the above case, the garbage collection algorithm does not group objects by application as it has no notion of this deployment model. Therefore, object allocations by two isolated applications that share a container do interfere with the anticipated collection patterns of one another. If each application relies on its objects to die young, the sharing of a heap causes a strong relativity on the duration of short-lived.

I am not an advocate for microservices. As a matter of fact, I think they are a bad idea for most applications. In my opinion, routines that can only exist in interaction should ideally be deployed together unless there are good technical reasons not to. And even if isolated applications ease development, you quickly pay the price in operations. I am just mentioning this to avoid a misinterpretation of the moral of the above experience.

What this experience taught me was that deploying several applications in a single Java process can be a bad idea if those applications are heterogeneous. For example, when running a batch process parallel to a web server, you should consider running each in its own process rather than deploying both of them in the same container. Typically, a batch process is allocating objects at a very different rate than a web server. Yet, many enterprise frameworks still advertise all-in-one solutions for tackling such problems which should not share a process to begin with. In 2016, the overhead of an additional process is not typically a problem and since memory is cheap, rather upgrade your server instead of sharing a heap. Otherwise, you might end up with collection patterns that you did not anticipate when developing, running and testing your applications in isolation.

Donnerstag, 17. Dezember 2015

I am elected Java Champion. Thank you!

Today I was elected a Java Champion. I want to take this opportunity to say thank you to everybody who supported me and my work. Without you, I would not be the developer that I am today. I want to thank all of you and especially:

Rafał Świerzyńsk for his patience and contagious enthusiasm when teaching me many programming fundamentals during my first full-time programming job. Thank you for proving to me that writing quality code pays off both in terms of joy at work and value for a customer.

The team at RebelLabs who helped me to promote Byte Buddy to a broader audience before anybody even used my software. Especially, I want to thank Simon Maple and Oleg Šelajev from ZeroTurnaround and Oliver White who is now working at Typesafe.

Axel Fontaine and Lukas Eder, both developers of open-source libraries that often served me as specimen for how to promote Byte Buddy. I also want to thank you both for your advice and shared experiences.

Everybody at javaBin, the Norwegian Java user group. My first presentation at a JUG meeting bootstrapped my speaker career and speaking at JavaZone gave me a lot of confidence for the international stage. You are a great bunch and I would surely not be a Java Champion today if it were not for your hard work and dedication.

The Java community for its countless efforts of documenting insights into Java technology, for its free software and the many great discussions that I have had. Anything I know I have learned from others and I am endlessly grateful. Especially, I want to thank Brice Dutheil who had the confidence to integrate Byte Buddy into the very popular Mockito library what motivated me tremendously.

Finally, my girlfriend Eiril who never complained when I was away for weeks of conferences, when I programmed away an entire weekend or was fed up with a problem that I had not yet figured out.

Thank you all, wholeheartedly!

Mittwoch, 2. Dezember 2015

Project Jigsaw: an incomplete puzzle

Mark Reinhold just recently proposed a delay of Java 9 to buy more time for completing project Jigsaw as the major feature of the upcoming release. While this decision will surely bring the doomsayers of Java back onto stage, I am personally quite relieved and think this was a good and necessary decision. The milestone for feature completion of Java 9 is
currently set to the 10th of December, forbidding the introduction of new functionality after that date. But looking at early access builds of project Jigsaw, Java’s module system does not seem to be ready for this development stage.

Delays in project Jigsaw have become a habit over the latest Java release cycles. This must not be misinterpreted as incompetence but rather as an indicator for how difficult it is to introduce modules to Java that is currently a stranger to true modularization. Initially, the module system for Java was proposed in 2008 for inclusion in Java 7. But until today, Jigsaw’s implementation always turned out to be more difficult than anticipated. And after several suspensions and even a temporary abandonment, the stewards of Java are surely under pressure to finally succeed. It is great to see that this pressure did not push the Java team to rush for a release.

In this article, I try to summarize the state of project Jigsaw as I see it and as it is discussed publicly on the Jigsaw mailing list. I am writing this article as a contribution to the current discussion and to hopefully involve more people into the ongoing development process. I do no intend to downplay the hard work done by Oracle. I am stating this explicitly to avoid misinterpretation after the rather emotional discussions about Jigsaw following the concealment of sun.misc.Unsafe.

Modularized reflection


What exactly is it that makes project Jigsaw such a difficult endeavor? Today, visibility modifiers are the closest approximation to encapsulating a class’s scope. Package-privacy can serve as an imperfect retainer of a type to its package. But for more complex applications that span internal APIs over multiple packages, visibility modifiers are insufficient and true modules become necessary. With project Jigsaw, classes can be truly encapsulated what makes them unavailable to some code even if those classes were declared to be public. However, Java programs that build on the assumption that all classes are always available at runtime might need to change fundamentally.

This change is most likely less fundamental for developers of end-user applications than for the maintainers of Java libraries and frameworks. A library is typically not aware of its user’s code during its compilation. For overcoming this limitation, a library can fallback to using reflection. This way, a container for dependency-injection (such as Spring) can instantiate bean instances of an application without the bean types being known to the framework at compile-time. For instantiating such objects, the container simply delays its work until runtime when it scans the application’s classpath and discovers the bean types which are now visible. For any of these types, the framework then locates a constructor which is invoked reflectively after resolving all injected dependencies.

Runtime discovery paired with reflection is used by a long list of Java frameworks. But in a modularized environment, running the previous runtime resolution is no longer possible without addressing module boundaries. With project Jigsaw, the Java runtime asserts that every module only accesses modules that are declared as a dependency in the accessing module’s descriptor. Additionally, the imported module must export the classes in question to its accessor. A modularized version of the dependency-injection container cannot declare any user module as a dependency and it is then forbidden reflective access. This would result in a runtime error when instantiating a non-imported class.

To overcome this limitation, project Jigsaw adds a new API that allows to include additional module dependencies at runtime. After making use of this API and adding all user modules, the modularized dependency-injection container can now continue to instantiate bean types that it does not know at compile-time.

But does this new API really solve the problem? From a purely functional point of view, this additional API allows for the migration of a library to retain its functionality even after being repackaged as a module. But unfortunately, the runtime enforcement of module boundaries creates a requirement for a ceremonial dance preceding the use of most reflection code. Before a method is invoked, the caller needs to always assure that the corresponding module is already a dependency of the caller. If a framework forgets to add this check, a runtime error is thrown without any chance of discovery during compilation.

With reflection being used excessively by many libraries and frameworks, it is unlikely that this change in accessibility is going to improve runtime encapsulation. Even if a security manager would restrict frameworks from adding runtime module dependencies, enforcing such boundaries would probably break most existing applications. More realistically, most breaches of module boundaries will not indicate true errors but be caused by improperly migrated code. At the same time, the runtime restriction is neither likely to improve encapsulation if most frameworks preemptively attain access to most user modules.

This requirement does of course not apply when a module uses reflection on its own types but such use of reflection is rather rare in practice and can be substituted by the use of polymorphism. In my eyes, enforcing module boundaries when using reflection contradicts its primary use case and makes the already non-trivial reflection API even more difficult to use.

Modularized resources


Beyond this limitation, it is currently unclear how the dependency-injection container would even discover the classes that it should instantiate. In a non-modularized application, a framework can for example expect a file of a given name to exist on the classpath. This file then serves as an entry point for describing how user code can be discovered. This file is typically obtained by requesting a named resource from a class loader. With project Jigsaw, this might no longer be possible when the required resource is also encapsulated within a module’s boundaries. As far as I know, the final state of resource encapsulation is not yet fully determined. When trying current early access builds, resources of foreign modules can however not be accessed.

Of course, this problem is also addressed in project Jigsaw’s current draft. To overcome module boundaries, Java’s preexisting ServiceLoader class is granted super powers. For making specific classes available to other modules, a module descriptor provides a special syntax that enables leaking certain classes through module boundaries. Applying this syntax, a framework module declares that it provides a certain service. A user library then declares an implementation of the same service to be accessible to the framework. At runtime, the framework module looks up any implementation of its service using the service loader API. This can serve as way for discovering other modules at runtime and could substitute resource discovery.

While this solution seems elegant on a first glance, I remain sceptical of this proposal. The service loader API is fairly simple to use but at the same time, it is very limited in its capabilities. Furthermore, few people have adapted it for their own code which could be seen as an indicator for its limited scope. Unfortunately, only time can tell if this API accommodates all use cases in a sufficient manner. At the same time it is granted that a single Java class gets tied deeply into the Java runtime, making deprecation and substitution of the service loader API almost impossible. In the context of the history of Java which has already told many stories about ideas that seemed good but turned sour, I find it precarious to create such a magical hub that could easily turn out to be an implementation bottleneck.

Finally, it remains unclear how resources are exposed in modularized applications. While Jigsaw does not break any binary compatibility, returning null from a call to ClassLoader::getResource where a value was always returned previously might just bury applications under piles of null pointer exceptions. As an example, code manipulation tools require a means to locate class files which are now encapsulated what would at a minimum hinder their adoption process.

Optional dependencies


Another use case that the service loader API does not accommodate is the declaration of optional dependencies. In many cases, optional dependencies are not considered a good practice but in reality they offer a convenient way out if dependencies can be combined in a large number of permutations.

For example, a library might be able to provide better performance if a specific dependency is available. Otherwise, it would fall back to another, less optimal alternative. In order to use the optional dependency, the library is required to compile against its specific API. If this API is however not available at runtime, the library needs to assure that the optional code is never executed and fall back to the available default. Such an optional dependency cannot be expressed in a modularized environment where any declared module dependency is validated upon the application’s startup, even if the dependency was never used.

A special use-case for optional dependencies are optional annotation bundles. Today, the Java runtime treats annotations as optional metadata. This means that if an annotation’s type cannot be located by a class loader, the Java runtime simply ignores the annotation in question instead of throwing a NoClassDefFoundError. For example, the FindBugs application offers an annotation bundle for suppressing potential bugs after a user found the code in question to be a false-positive. During an application’s regular runtime, the FindBugs-specific annotations are not required and are therefore not included in the application bundle. However, when running FindBugs, the utility explicitly adds the annotation package such that the annotations become visible. In project Jigsaw, this is no longer possible. The annotation type is only available if a module declares a dependency to the annotation bundle. If this dependency is later missing at runtime, an error is raised, despite the annotation's irrelevance.

Non-modularization


Not bundling a framework as a module in Java 9 is of course the easiest way to avoid all of the discussed restrictions. The Java runtime considers any non-modularized jar-file to be part of a class loader’s so-called unnamed module. This unnamed module defines an implicit dependency on all other modules that exist within the running application and exports all of its packages to any other module. This serves as a fallback when mixing modularized and non-modularized code. Due to the implicit imports and exports of an unnamed module, all non-migrated code should continue to function as before.

While such an opt-out might be the best solution for a reflection-heavy framework, slow adoption of project Jigsaw does also defeat the purpose of a module system. With a lack of time being the major constraint of most open-source projects, this outcome is unfortunately quite probable. Furthermore, many open-source developers are bound to compiling their libraries to older versions of Java. Due to the different runtime behavior of modularized and non-modularized code, a framework would need to maintain two branches for being able to use Java 9 APIs to traverse module boundaries in the modularized bundle. It is unlikely that many open-source developers would make the time for such a hybrid solution.

Code instrumentation


In Java, reflective method access is not the only way of a library to interact with unknown user code. Using the instrumentation API, it is possible to redefine classes to include additional method calls. This is commonly used to for example implement method-level security or to collect code metrics.

When instrumenting code, the bytecode of a Java class is typically altered right before it is loaded by a class loader. This can cause unresolvable conflicts if the instrumenting code cannot access a loaded class before its first usage. Currently, there exists no solution to this problem.

Summary


Software estimates are difficult and we all tend to underestimate the complexity of our applications. Project Jigsaw imposes a fundamental change to the runtime behavior of Java applications and it makes perfect sense to delay the release until every eventuality is thoroughly evaluated. Currently, there are too many open questions and it is a good choice to delay the release date.

I would prefer that module boundaries were not enforced by the runtime at all but remain a compiler construct. The Java platform already implements compile-time erasure of generic types and despite some imperfections this solution has worked very well. Without runtime enforcement, modules would also be optional to adopt for dynamic languages on the JVM where the same form of modularization as in Java might not make sense. Finally, I feel that the current strict form of runtime encapsulation tries to solve a problem that does not exist. After working with Java for many years, I have rarely encountered situations where the unintentional usage of internal APIs has caused big problems. In contrast, I remember many occasions where abusing an API that was meant to be private has solved a problem that I could not have worked around. At the same time, other symptoms of lacking modules in Java, often referred to as jar hell, remain unsolved by Jigsaw which does not distinguish between different versions of a module.

Finally, I argue that backwards compatibility applies beyond the binary level. As a matter of fact, a binary incompatibility is usually easier to deal with than a behavioral change. Therefore, method contracts should be respected at least as highly as binary compatibility. In this context, Java has done a great job over the years. While project Jigsaw does not technically break method contracts by providing unnamed modules, modularization makes subtle changes to code behavior that is based on its bundling. In my opinion, this will be confusing to both experienced Java developers and newcomers and result in reappearing runtime errors.

This is why I find the price for enforcing runtime module boundaries too high compared to the benefits that it offers. OSGi, a runtime module system with versioning capabilities already exists for those that really require modularization. As a big benefit, OSGi is implemented on top of the virtual machine and can therefore not influence VM behavior. Alternatively, I think that Jigsaw could include a canonical way for libraries to opt-out of runtime constraints where it makes sense such as for reflection-heavy libraries.

Montag, 30. März 2015

Dismantling invokedynamic

Many Java developers regarded the JDK's version seven release as somewhat a disappointment. On the surface, merely a few language and library extensions made it into the release, namely Project Coin and NIO2. But under the covers, the seventh version of the platform shipped the single biggest extension to the JVM's type system ever introduced after its initial release. Adding the invokedynamic instruction did not only lay the foundation for implementing lambda expressions in Java 8, it also was a game changer for translating dynamic languages into the Java byte code format.

While the invokedynamic instruction is an implementation detail for executing a language on the Java virtual machine, understanding the functioning of this instruction gives true insights into the inner workings of executing a Java program. This article gives a beginner's view on what problem the invokedynamic instruction solves and how it solves it.

Method handles


Method handles are often described as a retrofitted version of Java's reflection API, but this is not what they are meant to represent. While method handles can represent a method, constructor or field, they are not intended to describe properties of these class members. It is for example not possible to directly extract metadata from a method handle such as modifiers or annotation values of the represented method. And while method handles allow for the invocation of a referenced method, their main purpose is to be used together with an invokedynamic call site. For gaining a better understanding of method handles, looking at them as an imperfect replacement for the reflection API is however a reasonable starting point.

Method handles cannot be instantiated. Instead, method handles are created by using a designated lookup object. These objects are themselves created by using a factory method that is provided by the MethodHandles class. Whenever this factory is invoked, it first creates a security context which ensures that the resulting lookup object can only locate methods that are also visible to the class from which the factory method was invoked. A lookup object can then be created as follows:

class Example {
  void doSomething() {
    MethodHandles.Lookup lookup = MethodHandles.lookup();
  }
  private void foo() { /* ... */ }
}

As argued before, the above lookup object could only be used to locate methods that are also visible to the Example class such as foo. It would for example be impossible to look up a private method of another class. This is a first major difference to using the reflection API where private methods of outside classes can be located just as any other method and where these methods can even be invoked after marking such a method as accessible. Method handles are therefore sensible of their creation context which is a first major difference to the reflection API.

Apart from that, a method handle is more specific than the reflection API by describing a specific type of method rather than representing just any method. In a Java program, a method's type is a composite of both the method's return type and the types of its parameters. For example, the only method of the following Counter class returns an int representing the number of characters of the only String-typed argument:

class Counter {
  static int count(String name) {
    return name.length();
  }
}

A representation of this method's type can be created by using another factory. This factory is found in the MethodType class which also represents instances of created method types. Using this factory, the method type for Counter::count can be created by handing over the method's return type and its parameter types bundled as an array:

MethodType methodType = MethodType.methodType(int.class, new Class<?>[] {String.class});

By using the lookup object that was created before and the above method type, it is now possible to locate a method handle that represents the Counter::count method as depicted in the following code:

MethodType methodType = MethodType.methodType(int.class, new Class<?>[] {String.class});
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle methodHandle = lookup.findStatic(Counter.class, "count", methodType);
int count = methodHandle.invokeExact("foo");
assertThat(count, is(3));

At first glance, using a method handle might seem like an overly complex version of using the reflection API. However, keep in mind that the direct invocation of a method using a handle is not the main intent of its use.

The main difference of the above example code and of invoking a method via the reflection API is only revealed when looking into the differences of how the Java compiler translates both invocations into Java byte code. When a Java program invokes a method, this method is uniquely identified by its name and by its (non-generic) parameter types and even by its return type. It is for this reason that it is possible to overload methods in Java. And even though the Java programming language does not allow it, the JVM does in theory allow to overload a method by its return type.

Following this principle, a reflective method call is executed as a common method call of the Method::invoke method. This method is identified by its two parameters which are of the types Object and Object[]. In addition to this, the method is identified by its Object return type. Because of this signature, all arguments to this method need to always be boxed and enclosed in an array. Similarly, the return value needs to be boxed if it was primitive or null is returned if the method was void.

Method handles are the exception to this rule. Instead of invoking a method handle by referring to the signature of MethodHandle::invokeExact signature which takes an Object[] as its single argument and returns Object, method handles are invoked by using a so-called polymorphic signature. A polymorphic signature is created by the Java compiler dependant on the types of the actual arguments and the expected return type at a call site. For example, when invoking the method handle as above with

int count = methodHandle.invokeExact("foo");

the Java compiler translates this invocation as if the invokeExact method was defined to accept a single single argument of type String and returning an int type. Obviously, such a method does not exist and for (almost) any other method, this would result in a linkage error at runtime. For method handles, the Java Virtual Machine does however recognize this signature to be polymorphic and treats the invocation of the method handle as if the Counter::count method that the handle refers to was inset directly into the call site. Thus, the method can be invoked without the overhead of boxing primitive values or the return type and without placing the argument values inside an array.

At the same time, when using the invokeExact invocation, it is guaranteed to the Java virtual machine that the method handle always references a method at runtime that is compatible to the polymorphic signature. For the example, the JVM expected that the referenced method actually accepts a String as its only argument and that it returns a primitive int. If this constraint was not fulfilled, the execution would instead result in a runtime error. However, any other method that accepts a single String and that returns a primitive int could be successfully filled into the method handle's call site to replace Counter::count.

In contrast, using the Counter::count method handle at the following three invocations would result in runtime errors, even though the code compiles successfully:

int count1 = methodHandle.invokeExact((Object) "foo");
int count2 = (Integer) methodHandle.invokeExact("foo");
methodHandle.invokeExact("foo");

The first statement results in an error because the argument that is handed to the handle is too general. While the JVM expected a String as an argument to the method, the Java compiler suggested that the argument would be an Object type. It is important to understand that the Java compiler took the casting as a hint for creating a different polymorphic signature with an Object type as a single parameter type while the JVM expected a String at runtime. Note that this restriction also holds for handing too specific arguments, for example when casting an argument to an Integer where the method handle required a Number type as its argument. In the second statement, the Java compiler suggested to the runtime that the handle's method would return an Integer wrapper type instead of the primitive int. And without suggesting a return type at all in the third statement, the Java compiler implicitly translated the invocation into a void method call. Hence, invokeExact really does mean exact.

This restriction can sometimes be too harsh. For this reason, instead of requiring an exact invocation, the method handle also allows for a more forgiving invocation where conversions such as type castings and boxings are applied. This sort of invocation can be applied by using the MethodHandle::invoke method. Using this method, the Java compiler still creates a polymorphic signature. This time, the Java virtual machine does however test the actual arguments and the return type for compatibility at run time and converts them by applying boxings or castings, if appropriate. Obviously, these transformations can sometimes add a runtime overhead.

Fields, methods and constructors: handles as a unified interface


Other than Method instances of the reflection API, method handles can equally reference fields or constructors. The name of the MethodHandle type could therefore be seen as too narrow. Effectively, it does not matter what class member is referenced via a method handle at runtime as long as its MethodType, another type with a misleading name, matches the arguments that are passed at the associated call site.

Using the appropriate factories of a MethodHandles.Lookup object, a field can be looked up to represent a getter or a setter. Using getters or setters in this context does not refer to invoking an actual method that follows the Java bean specification. Instead, the field-based method handle directly reads from or writes to the field but in shape of a method call via invoking the method handle. By representing such field access via method handles, field access or method invocations can be used interchangeably.

As an example for such interchange, take the following class:

class Bean {
  String value;
  void print(String x) {
    System.out.println(x);
  }
}

For the above Bean class, the following method handles can be used for either writing a string to the value field or for invoking the print method with the same string as an argument:

MethodHandle fieldHandle = lookup.findSetter(Bean.class, "value", String.class);
MethodType methodType = MethodType.methodType(void.class, new Class<?>[] {String.class});
MethodHandle methodHandle = lookup.findVirtual(Bean.class, "print", methodType);

As long as the method handle call site is handed an instance of Bean together with a String while returning void, both method handles could be used interchangeably as shown here:

anyHandle.invokeExact((Bean) mybean, (String) myString);

Note that the polymorphic signature of the above call site does not match the method type of the above handle. However, within Java byte code, non-static methods are invoked as if they were static methods with where the this reference is handed as a first, implicit argument. A non-static method's nominal type does therefore diverge from its actual runtime type. Similarly, access to a non-static field requires an instance to be access.

Similarly to fields and methods, it is possible to locate and invoke constructors which are considered as methods with a void return value for their nominal type. Furthermore, one can not only invoke a method directly but even invoke a super method as long as this super method is reachable for the class from which the lookup factory was created. In contrast, invoking a super method is not possible at all when relying on the reflection API. If required, it is even possible to return a constant value from a handle.

Performance metrics


Method handles are often described as being a more performant as the Java reflection API. At least for recent releases of the HotSpot virtual machine, this is not true. The simplest way of proving this is writing an appropriate benchmark. Then again, is not all too simple to write a benchmark for a Java program which is optimized while it is executed. The de facto standard for writing a benchmark has become using JMH, a harness that ships under the OpenJDK umbrella. The full benchmark can be found as a gist in my GitHub profile. In this article, only the most important aspects of this benchmark are covered.

From the benchmark, it becomes obvious that reflection is already implemented quite efficiently. Modern JVMs know a concept named inflation where a frequently invoked reflective method call is replaced with runtime generated Java byte code. What remains is the overhead of applying the boxing for passing arguments and receiving a return values. These boxings can sometimes be eliminated by the JVM's Just-in-time compiler but this is not always possible. For this reason, using method handles can be more performant than using the reflection API if method calls involve a significant amount of primitive values. This does however require that the exact method signatures are already known at compile time such that the appropriate polymorphic signature can be created. For most use cases of the reflection API, this guarantee can however not be given because the invoked method's types are not known at compile time. In this case, using method handles does not offer any performance benefits and should not be used to replace it.

Creating an invokedynamic call site


Normally, invokedynamic call sites are created by the Java compiler only when it needs to translate a lambda expression into byte code. It is worthwhile to note that lambda expressions could have been implemented without invokedynamic call sites altogether, for example by converting them into anonymous inner classes. As a main difference to the suggested approach, using invokedynamic delays the creation of a similar class to runtime. We are looking into class creation in the next section. For now, bear however in mind that invokedynamic does not have anything to do with class creation, it only allows to delay the decision of how to dispatch a method until runtime.

For a better understanding of invokedynamic call sites, it helps to create such call sites explicitly in order to look at the mechanic in isolation. To do so, the following example makes use of my code generation framework Byte Buddy which provides explicit byte code generation of invokedynamic call sites without requiring a any knowledge of the byte code format.

Any invokedynamic call site eventually yields a MethodHandle that references the method to be invoked. Instead of invoking this method handle manually, it is however up to the Java runtime to do so. Because method handles have become a known concept to the Java virtual machine, these invocations are then optimized similarly to a common method call. Any such method handle is received from a so-called bootstrap method which is nothing more than a plain Java method that fulfills a specific signature. For a trivial example of a bootstrap method, look at the following code:

class Bootstrapper {
  public static CallSite bootstrap(Object... args) throws Throwable {
    MethodType methodType = MethodType.methodType(int.class, new Class<?>[] {String.class})
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle methodHandle = lookup.findStatic(Counter.class, "count", methodType);
    return new ConstantCallSite(methodHandle);
  }
}

For now, we do not care much about the arguments of the method. Instead, notice that the method is static what is as a matter of fact a requirement. Within Java byte code, an invokedynamic call site references the full signature of a bootstrap method but not a specific object which could have a state and a life cycle. Once the invokedynamic call site is invoked, control flow is handed to the referenced bootstrap method which is now responsible for identifying a method handle. Once this method handle is returned from the bootstrap method, it is invoked by the Java runtime.

As obvious from the above example, a MethodHandle is not returned directly from a bootstrap method. Instead, the handle is wrapped inside of a CallSite object. Whenever a bootstrap method is invoked, the invokedynamic call site is later permanently bound to the CallSite object that is returned from this method. Consequently, a bootstrap method is only invoked a single time for any call site. Thanks to this intermediate CallSite object, it is however possible to exchange the referenced MethodHandle at a later point. For this purpose, the Java class library already offers different implementations of CallSite. We have already seen a ConstantCallSite in the example code above. As the name suggests, a ConstantCallSite always references the same method handle without a possibility of a later exchange. Alternatively, it is however also possible to for example use a MutableCallSite which allows to change the referenced MethodHandle at a later point in time or it is even possible to implement a custom CallSite class.

With the above bootstrap method and Byte Buddy, we can now implement a custom invokedynamic instruction. For this, Byte Buddy offers the InvokeDynamic instrumentation that accepts a bootstrap method as its only mandatory argument. Such instrumentations are then fed to Byte Buddy. Assuming the following class:

abstract class Example {
  abstract int method();
}

we can use Byte Buddy to subclass Example in order to override method. We are then going to implement this method to contain a single invokedynamic call site. Without any further configuration, Byte Buddy creates a polymorphic signature that resembles the method type of the overridden method. However, for non-static methods, the this reference is set as a first, implicit argument. Assuming that we want to bind the Counter::count method which expects a String as a single argument, we could not bind this handle to Example::method because of this type mismatch. Therefore, we need to create a different call site without the implicit argument but with an String in its place. This can be achieved by using Byte Buddy's domain specific language:

Instrumentation invokeDynamic = InvokeDynamic
 .bootstrap(Bootstrapper.class.getDeclaredMethod(“bootstrap”, Object[].class))
 .withoutImplicitArguments()
 .withValue("foo");

With this instrumentation in place, we can finally extend the Example class and override method to implement the invokedynamic call site as in the following code snippet:

Example example = new ByteBuddy()
  .subclass(Example.class)
   .method(named(“method”)).intercept(invokeDynamic)
   .make()
   .load(Example.class.getClassLoader(), 
         ClassLoadingStrategy.Default.INJECTION)
   .getLoaded()
   .newInstance();
int result = example.method();
assertThat(result, is(3));

As obvious from the above assertion, the characters of the "foo" string were counted correctly. By setting appropriate break points in the code, it is further possible to validate that the bootstrap method is called and that control flow further reaches the Counter::count method.

So far, we did not gain much from using an invokedynamic call site. The above bootstrap method would always bind Counter::count and can therefore only produce a valid result if the invokedynamic call site really wanted to transform a String into an int. Obviously, bootstrap methods can however be more flexible thanks to the arguments they receive from the invokedynamic call site. Any bootstrap method receives at least three arguments:

As a first argument, the bootstrap method receives a MethodHandles.Lookup object. The security context of this object is that of the class that contains the invokedynamic call site that triggered the bootstrapping. As discussed before, this implies that private methods of the defining class could be bound to the invokedynamic call site using this lookup instance.
The second argument is a String representing a method name. This string serves as a hint to indicate from the call site which method should be bound to it. Strictly speaking, this argument is not required as it is perfectly legal to bind a method with another name. Byte Buddy simply serves the the name of the overridden method as this argument, if not specified differently.
Finally, the MethodType of the method handle that is expected to be returned is served as a third argument. For the example above, we specified explicitly that we expect a String as a single parameter. At the same time, Byte Buddy derived that we require an int as a return value from looking at the overridden method, as we again did not specify any explicit return type.

It is up to the implementor of a bootstrap method what exact signature this method should portray as long as it can at least accept these three arguments. If the last parameter of a bootstrap method represents an Object array, this last parameter is treated as a varargs and can therefore accept any excess arguments. This is also the reason why the above example bootstrap method is valid.

Additionally, a bootstrap method can receive several arguments from an invokedynamic call site as long as these arguments can be stored in a class's constant pool. For any Java class, a constant pool stores values that are used inside of a class, largely numbers or string values. As of today, such constants can be primitive values of at least 32 bit size, Strings, Classes, MethodHandles and MethodTypes. This allows bootstrap methods to be used more flexible, if locating a suitable method handle requires additional information in form of such arguments.

Lambda expressions


Whenever the Java compiler translates a lambda expression into byte code, it copies the lambda's body into a private method inside of the class in which the expression is defined. These methods are named lambda$X$Y with X being the name of the method that contains the lambda expression and with Y being a zero-based sequence number. The parameters of such a method are those of the functional interface that the lambda expression implements. Given that the lambda expression makes no use of non-static fields or methods of the enclosing class, the method is also defined to be static.

For compensation, the lambda expression is itself substituted by an invokedynamic call site. On its invocation, this call site requests the binding of a factory for an instance of the functional interface. As arguments to this factory, the call site supplies any values of the lambda expression's enclosing method which are used inside of the expression and a reference to the enclosing instance, if required. As a return type, the factory is required to provide an instance of the functional interface.

For bootstrapping a call site, any invokedynamic instruction currently delegates to the LambdaMetafactory class which is included in the Java class library. This factory is then responsible for creating a class that implements the functional interface and which invokes the appropriate method that contains the lambda's body which, as described before, is stored in the original class. In the future, this bootstrapping process might however change which is one of the major advantages of using invokedynamic for implementing lambda expressions. If one day, a better suited language feature was available for implementing lambda expressions, the current implementation could simply be swapped out.

In order to being able to create a class that implements the functional interface, any call site representing a lambda expression provides additional arguments to the bootstrap method. For the obligatory arguments, it already provides the name of the functional interface's method. Also, it provides a MethodType of the factory method that the bootstrapping is supposed to yield as a result. Additionally, the bootstrap method is supplied another MethodType that describes the signature of the functional interface's method. To that, it receives a MethodHandle referencing the method that contains the lambda's method body. Finally, the call site provides a MethodType of the generic signature of the functional interface's method, i.e. the signature of the method at the call site before type-erasure was applied.

When invoked, the bootstrap method looks at these arguments and creates an appropriate implementation of a class that implements the functional interface. This class is created using the ASM library, a low-level byte code parser and writer that has become the de facto standard for direct Java byte code manipulation. Besides implementing the functional interface's method, the bootstrap method also adds an appropriate constructor and a static factory method for creating instances of the class. It is this factory method that is later bound to the invokedyanmic call site. As arguments, the factory receives an instance to the lambda method's enclosing instance, in case it is accessed and also any values that are read from the enclosing method.

As an example, consider the following lambda expression:

class Foo {
  int i;
  void bar(int j) {
    Consumer consumer = k -> System.out.println(i + j + k);
  }
}

In order to be executed, the lambda expression requires access to both the enclosing instance of Foo and to the value j of its enclosing method. Therefore, the desugared version of the above class looks something like the following where the invokedynamic instruction is represented by some pseudo-code:

class Foo {
  int i;
  void bar(int j) {
    Consumer consumer = <invokedynamic(this, j)>;
  }
  private /* non-static */ void lambda$foo$0(int j, int k) {
    System.out.println(this.i + j + k);
  }
}

In order to being able to invoke lambda$foo$0, both the enclosing Foo instance and the j variable are handed to the factory that is bound by the invokedyanmic instruction. This factory then receives the variables it requires in order to create an instance of the generated class. This generated class would then look something like the following:

class Foo$$Lambda$0 implements Consumer {
  private final Foo _this;
  private final int j;
  private Foo$$Lambda$0(Foo _this, int j) {
    this._this = _this;
    this.j = j;
  }
  private static Consumer get$Lambda(Foo _this, int j) {
    return new Foo$$Lambda$0(_this, j);
  }
  public void accept(Object value) { // type erasure
    _this.lambda$foo$0(_this, j, (Integer) value);
  }
}

Eventually, the factory method of the generated class is bound to the invokedynamic call site via a method handle that is contained by a ConstantCallSite. However, if the lambda expression is fully stateless, i.e. it does not require access to the instance or method in which it is enclosed, the LambdaMetafactory returns a so-called constant method handle that references an eagerly created instance of the generated class. Hence, this instance serves as a singleton to be used for every time that the lambda expression's call site is reached. Obviously, this optimization decision affects your application's memory footprint and is something to keep in mind when writing lambda expressions. Also, no factory method is added to a class of a stateless lambda expression.

You might have noticed that the lambda expression's method body is contained in a private method which is now invoked from another class. Normally, this would result in an illegal access error. To overcome this limitation, the generated classes are loaded using so-called anonymous class loading. Anonymous class loading can only be applied when a class is loaded explicitly by handing a byte array. Also, it is not normally possible to apply anonymous class loading in user code as it is hidden away in the internal classes of the Java class library. When a class is loaded using anonymous class loading, it receives a host class of which it inherits its full security context. This involves both method and field access rights and the protection domain such that a lambda expression can also be generated for signed jar files. Using this approch, lambda expression can be considered more secure than anonymous inner classes because private methods are never reachable from outside of a class.

Under the covers: lambda forms


Lambda forms are an implementation detail of how MethodHandles are executed by the virtual machine. Because of their name, lambda forms are however often confused with lambda expressions. Instead, lambda forms are inspired by lambda calculus and received their name for that reason, not for their actual usage to implement lambda expressions in the OpenJDK.

In earlier versions of the OpenJDK 7, method handles could be executed in one of two modes. Method handles were either directly rendered as byte code or they were dispatched using explicit assembly code that was supplied by the Java runtime. The byte code rendering was applied to any method handle that was considered to be fully constant throughout the lifetime of a Java class. If the JVM could however not prove this property, the method handle was instead executed by dispatching it to the supplied assembly code. Unfortunately, because assembly code cannot be optimized by Java's JIT-compiler, this lead to non-constant method handle invocations to "fall off the performance cliff". As this also affected the lazily bound lambda expressions, this was obviously not a satisfactory solution.

LambdaForms were introduced to solve this problem. Roughly speaking, lambda forms represent byte code instructions which, as stated before, can be optimized by a JIT-compiler. In the OpenJDK, a MethodHandle's invocation semantics are today represented by a LambdaForm to which the handle carries a reference. With this optimizable intermediate representation, the use of non-constant MethodHandles has become significantly more performant. As a matter of fact, it is even possible to see a byte-code compiled LambdaForm in action. Simply place a break point inside of a bootstrap method or inside of a method that is invoked via a MethodHandle. Once the break point kicks it, the byte code-translated LambdaForms can be found on the call stack.

Why this matters for dynamic languages


Any language that should be executed on the Java virtual machine needs to be translated to Java byte code. And as the name suggests, Java byte code aligns rather close to the Java programming language. This includes the requirement to define a strict type for any value and before invokedynamic was introduced, a method call required to specify an explicit target class for dispatching a method. Looking at the following JavaScript code, specifying either information is however not possible when translating the method into byte code:

function (foo) {
  foo.bar();
}

Using an invokedynamic call site, it has become possible to delay the identification of the method's dispatcher until runtime and furthermore, to rebind the invocation target, in case that a previous decision needs to be corrected. Before, using the reflection API with all of its performance drawbacks was the only real alternative to implementing a dynamic language.

The real profiteer of the invokedynamic instruction are therefore dynamic programming languages. Adding the instruction was a first step away from aligning the byte code format to the Java programming language, making the JVM a powerful runtime even for dynamic languages. And as lambda expressions proved, this stronger focus on hosting dynamic languages on the JVM does neither interfere with evolving the Java language. In contrast, the Java programming languages gained from these efforts.

Freitag, 9. Januar 2015

Make agents, not frameworks

Ever since their introduction, Java annotations have become an integral part of the APIs of larger application frameworks. Good examples for such APIs are those of Spring or Hibernate where adding a few lines of annotation code implements quite complex program logic. And while one can argue about the drawbacks of these particular APIs, most developers would agree that this form of declarative programming is quite expressive when used right. However, only few developers choose to implement annotation-based APIs for their own frameworks or application middleware, mainly because they are regarded as difficult to realize. In the following article, I want to convince you that such APIs are in contrast quite trivial to implement and, using the right tools, do not require any special knowledge of Java intrinsics.

One problem that becomes quite obvious when implementing an annotation-based API is that annotations are not being handled by an executing Java runtime. As a consequence, it is not possible to assign a specific meaning to a given user annotation. For example, consider that we wanted to define a @Log annotation which we want to provide for simply logging each invocation of an annotated method:

class Service {
  @Log
  void doSomething() { 
    // do something ...
  }
}

As the @Log annotation is not capable of executing program logic by its mere existence, it would be up to the annotation's user to perform the requested logging. Obviously, this renders the annotation almost useless as we cannot invoke the doSomething method and expect to observe a corresponding statement in our log. So far, the annotation only serves as a marker without contributing any program logic.

Bridging the gap


In order to overcome this glaring limitation, many annotation-driven frameworks use subclassing in combination with method overriding to implement the logic that is associated with a particular annotation. This is commonly referred to as subclass instrumentation. For the proposed @Log annotation, subclass instrumentation would result in creating a class similar to the following LoggingService:

class LoggingService extends Service {
  @Override
  void doSomething() { 
    Logger.log("doSomething() was called");
    super.doSomething();
  }
}

Of course, the above class does not normally need to be implemented explicitly. Instead, it is a popular approach to generate such classes only at runtime using a code generation library such as cglib or Javassist. Both these libraries offer simple APIs for creating program enhancing subclasses. As a nice side effect of delaying the class's creation until runtime, the proposed logging framework would be usable without any specific preparation and would always stay in sync with the user's code. Neither would be the case if the class would be created in a more explicit manner, for example by writing a Java source file during a build process.

But, does it scale?


However, this solution brings along another drawback. By placing the annotation's logic into the generated subclass, one must not longer instantiate the example Service class by its constructor. Otherwise, invocations of annotated methods would still not be logged: Obviously, calling the constructor does not create an instance of the required subclass. And to make things worse - when using the suggested approach of runtime generation - the LoggingService cannot be instantiated directly either as the Java compiler does not know about the runtime-generated class.

For this reason, frameworks such as Spring or Hibernate use object factories and do not allow for direct instantiation of objects that are considered to be a part of their framework logic. With Spring, creating objects by a factory comes naturally as all of Spring's objects are already managed beans which are to be created by the framework in the first place. Similarly, most Hibernate entities are created as a result of a query and are thus not instantiated explicitly. However, when for example saving an entity instance that is not yet represented in the database, a user of Hibernate needs to substitute a recently saved instance with an instance that is returned from Hibernate after storage. From looking at questions on Hibernate, ignoring this substitution already renders a common beginner's mistake. Other than that, thanks to these factories in place, subclass instrumentation happens mostly transparent to a framework user because Java's type system implies that a subclass can substitute any of its super classes. Hence, an instance of LoggingService can be used everywhere a user would expect an instance of the user-defined Service class.

Unfortunately, this approved method of instance factories proves difficult for implementing the proposed @Log annotation as this would entail using a factory for every single instance of a potentially annotated class. Obviously, this would add a tremendous amount of boilerplate code. Probably, we would even create more boilerplate than we avoid by not hard-coding the logging instruction into the methods. Also, the accidental use of a constructor would introduce subtle bugs to a Java program because the annotations on such instances would not longer be treated as we expect them to be. As another problem, factories are not easily composable. What if we wanted to add a @Log annotation to a class that already is a Hibernate bean? This sounds trivial but would require extensive configuration to merge both framework's factories. And finally, the resulting, factory-bloated code would not turn out too pretty to read and migrations to using the framework would be costly to implement. This is where instrumentation with Java agents comes into place. This underestimated form of instrumentation offers a great alternative to the discussed subclass instrumentation.

A simple agent


A Java agent is represented by a simple jar file. Similarly to normal Java programs, Java agents define some class as an entry point. This class is then expected to define a static method which is invoked before the actual Java program's main method is called:

class MyAgent {
  public static void premain(String args, Instrumentation inst) {
    // implement agent here ...
  }
}

The most interesting part when dealing with Java agents is the premain method's second argument which represents an instance of the Instrumentation interface. This interface offers a way of hooking into Java's class loading process by defining a ClassFileTransformer. With such transformers, we are able to enhance any class of a Java program before its first use.

While using this API might sound straight forward at first, it imposes a new challenge. Class file transformations are executed by altering compiled Java classes which are represented as Java byte code. As a matter of fact, the Java virtual machine has no notion of what Java, the programming language is. Instead, it only deals with this byte code. And it is also thanks to this byte code abstraction that the JVM is easily capable of running other languages such as Scala or Groovy. As a consequence, a registered class file transformer only offers to transform a given byte (code) array into another one.

Even though libraries such as ASM or BCEL offer an easy API for manipulating compiled Java classes, only few developers are experienced in working with raw byte code. To make things worse, getting byte code manipulation right is often cumbersome and even small mistakes are redeemed by the virtual machine with throwing a nasty and unrecoverable VerifierError. Fortunately, there are better, easier ways to manipulate byte code.

Byte Buddy, a library that I wrote and maintain, provides a simple API both for manipulating compiled Java classes and for creating Java agents. In some aspects, Byte Buddy is a code generation library similar to cglib and Javassist. However, other than those libraries, Byte Buddy offers a unified API for implementing subclasses and for redefining existing classes. For this article, we do however only want to look into redefining a class using a Java agent. Curious readers are referred to Byte Buddy's webpage which offers a detailed tutorial on its full feature set.

Using Byte Buddy for a simple agent


One way that Byte Buddy offers for defining an instrumentation, is using dependency injection. Doing so, an interceptor class - which is represented by any plain old Java object - simply requests any required information by annotations on its parameters. For example, by using Byte Buddy's @Origin annotation on a parameter of the Method type, Byte Buddy deducts that the interceptor wants to know about the method that is being intercepted. This way, we can define a generic interceptor that is always aware of the method that is being intercepted:

class LogInterceptor {
  static void log(@Origin Method method) {
    Logger.log(method + " was called");
  } 
}

Of course, Byte Buddy ships with many more annotations.

But how does this interceptor represent the logic that we intended for the proposed logging framework? So far, we only defined an interceptor that is logging the method call. What we miss is the subsequent invocation of the original code of the method. Fortunately, Byte Buddy's instrumentations are composable. First, we define a MethodDelegation to the recently defined LogInterceptor which by default invokes the interceptor's static method on every call of a method. Starting from this, we can then compose the delegation with a subsequent call of the original method's code which is represented by SuperMethodCall:

MethodDelegation.to(LogInterceptor.class)
  .andThen(SuperMethodCall.INSTANCE)

Finally, we need to inform Byte Buddy on the methods that are to be intercepted by the specified instrumentation. As we explained before, we want this instrumentation to apply for any method that is annotated with @Log. Within Byte Buddy, such a property of a method can be identified using an ElementMatcher which is similar to a Java 8 predicate. In the static utility class ElementMatchers, we can already find a suitable matcher for identifying methods with a given annotation: ElementMatchers.isAnnotatedWith(Log.class).

With all this, we can now define an agent that implements the suggested logging framework. For Java agents, Byte Buddy provides a utility API that builds on the class modification API that we just discussed. Similarly to this latter API, it is designed as a domain specific language such that its meaning should be easily understood only by looking at the implementation. As we can see, defining such an agent only requires a few lines of code:

class LogAgent {
  public static void premain(String args, Instrumentation inst) {
    new AgentBuilder.Default()
      .rebase(ElementMatchers.any())
      .transform( builder -> return builder
                              .method(ElementMatchers.isAnnotatedWith(Log.class))
                              .intercept(MethodDelegation.to(LogInterceptor.class)
                                  .andThen(SuperMethodCall.INSTANCE)) )
      .installOn(inst);
  }
}

Note that this minimal Java agent would not interfere with the remainder of the application as any executing code observes the instrumented Java classes just as if the logging statement was hard-coded into any annotated method.

What about real life?


Of course the presented agent-based logger is a trivial example. And often, broadly-scoped frameworks that offer similar features out-of-the-box such for example Spring or Dropwizard are great. However, such frameworks are equally often opinionated about how to approach programming problems. For a large number of software applications, this might not be a problem. And yet, sometimes these opinions are in the way of something bigger. Then, working around a framework's assumption on how to do things can cause more than just a few problems, often causes leaky abstractions and might just result in exploding costs for software maintenance. This is true especially when applications grow and change over time and diverge in their needs from what an underlying framework offers.

In contrast, when composing more specialized frameworks or libraries in a pic n mix fashion, one simply replaces problematic components with another one. And if this does not work either, one can even implement a custom solution without interfering with the rest of the application. As we learned, this seems difficult to realize on the JVM, mainly as a consequence of Java's strict type system. Using Java agents, it is however very much possible to overcome these typing constraints.

I came to the point where I believe that at least any cross-cutting concern should be covered by an agent-driven, specialized library instead of by a built-in module of a monolithic framework. And I really wish more applications would consider this approach. In the most trivial case, it is enough to use an agent to register listeners on methods of interest and to take it from there. This indirect approach of composing code modules avoids the strong cohesion that I observe in a large fraction of the Java applications I come across. As a nice side effect, It also makes testing very easy. And similarly to running tests, not adding an agent when starting up an application, allows to pointedly disable a certain application feature like for example logging. All this without changing a line of code and without crashing the application as the JVM simply ignores annotations that it cannot resolve at runtime. Security, logging, caching, there are many reasons that these topics and more should be taken care of in the suggested manner. Therefore, sometimes, make agents, not frameworks.

Freitag, 16. Mai 2014

Java 8 default methods can break your (users') code

At first glance, default methods brought a great new feature to the Java Virtual Machine's instruction set. Finally, library developers are able to evolve established APIs without introducing incompatibilities to their user's code. Using default methods, any user class that implements a library interface automatically adopts the default code when a new method is introduced to this interface. And once a user updates his implementing classes, he can simply override the default with something more meaningful to his particular use case. Even better, the user can call the default implementation of the interface from the overridden method and add logic around it.

So far, so good. However, adding default methods to established interfaces can render Java code uncompilable. This is easiest to understand when looking at an example. Let us assume a library that requires a class of one of its interfaces as its input:

interface SimpleInput {
  void foo();
  void bar();
}

abstract class SimpleInputAdapter implements SimpleInput {
  @Override
  public void bar() {
    // some default behavior ...
  }
}

Prior to Java 8, the above combination of an interface and a corresponding adapter class is a rather common pattern in the Java programming language. The adapter is usually offered by the library supplier to save the library's users some typing. However, the interface is offered additionally in order to allow an approximation of multiple inheritance.

Let us further assume that a user made use of this adapter:

class MyInput extends SimpleInputAdapter {
  @Override
  public void foo() {
    // do something ...
  }
  @Override
  public void bar() {
    super.bar();
    // do something additionally ...
  }
}

With this implementation, the user can finally interact with the library. Note how the implementation overrides the bar method to add some functionality to the default implementation.

So what happens if the library migrates to Java 8? First of all, the library will most likely deprecate the adapter class and move the functionality to default methods. As a result, the interface will now look like this:

interface SimpleInput {
  void foo();
  default void bar() {
    // some default behavior
  }
}

With this new interface, a user can update his code to adapt the default method instead of using the adapter class. The great thing about using interfaces instead of adapter classes is the ability to extend another class than the particular adapter. Let's put this into action and migrate the MyInput class to use the default method instead. Because we can now extend another class, let us additionally extend some third party base class. What this base class does is not of particular relevance here, so let us just assume that this makes sense for our use-case.

class MyInput extends ThirdPartyBaseClass implements SimpleInput {
  @Override
  public void foo() {
    // do something ...
  }
  @Override
  public void bar() {
    SimpleInput.super.bar();
    // do something additionally ... 
  }
}

To implement similar behavior as in the original class, we make use of Java 8's new syntax for calling a default method of a specific interface. Also, we moved the logic for myMethod to some base class MyBase. Clap on our shoulders. Nice refactoring here!

The library we are using is a great success. However, the maintainer needs to add another interface to offer more functionality. This interface represents a ComplexInput which extends the SimpleInput with an additional method. Because default methods are in general considered as being safe to add, the maintainer additionally overrides the SimpleInput's default method and adds some behavior to offer a better default. After all, doing so was quite common when implementing adapter classes:

interface ComplexInput extends SimpleInput {
  void qux();
  @Override
  default void bar() {
    SimpleInput.super.bar(); 
    // so complex, we need to do more ...
  }
} 

This new feature turns out so great that the maintainer of the ThirdPartyBaseClass decided to also rely on this library. For making this work, he implements the ComplexInput interface for the ThirdPartyLibrary.

But what does that mean to the MyInput class? Due to the implicit implementation of ComplexInput by extending ThirdPartyBaseClass, calling the default method of SimpleInput has suddenly become illegal. As a result, the user's code does not longer compile. Also, it is now generally forbidden to call this method since Java sees this call as illegal as calling a super-super method of an indirect super class. Instead, you could call the default method of the ComplexInput class. However, this would require you to first explicitly implement this interface in MyInput. For the user of the library, this change comes most likely rather unexpected!

Oddly enough, the Java runtime does not make this distinction. The JVM's verifier will allow a compiled class to call SimpleInput::foo even if the loaded class at run time implicitly implements the ComplexClass by extending the updated version of ThirdPartyBaseClass. It is only the compiler that complains here.

But what do we learn from this? In a nutshell, make sure to never override a default method in another interface. Neither with another default method, nor with an abstract method. In general, be careful about using default methods at all. As much as they ease the evolution of established APIs as Java's collection interfaces, they are intrinsically complex by allowing to perform method invocations that go sideways in your type hierarchy. Before Java 7, you would only need to look for the actually invoked code by traversing down a linear class hierarchy. Only add this complexity when you really feel it is absolutely necessary.

Donnerstag, 12. Dezember 2013

The infamous sun.misc.Unsafe explained

The biggest competitor to the Java virtual machine might be Microsoft's CLR that hosts languages such as C#. The CLR allows to write unsafe code as an entry gate for low level programming, something that is hard to achieve on the JVM. If you need such advanced functionality in Java, you might be forced to use the JNI which requires you to know some C and will quickly lead to code that is tightly coupled to a specific platform. With sun.misc.Unsafe, there is however another alternative to low-level programming on the Java plarform using a Java API, even though this alternative is discouraged. Nevertheless, several applications rely on sun.misc.Unsafe such for example objenesis and therewith all libraries that build on the latter such for example kryo which is again used in for example Twitter's Storm. Therefore, it is time to have a look, especially since the functionality of sun.misc.Unsafe is considered to become part of Java's public API in Java 9.

Getting hold of an instance of sun.misc.Unsafe


The sun.misc.Unsafe class is intended to be only used by core Java classes which is why its authors made its only constructor private and only added an equally private singleton instance. The public getter for this instances performs a security check in order to avoid its public use:

public static Unsafe getUnsafe() {
  Class cc = sun.reflect.Reflection.getCallerClass(2);
  if (cc.getClassLoader() != null)
    throw new SecurityException("Unsafe");
  return theUnsafe;
}

This method first looks up the calling Class from the current thread’s method stack. This lookup is implemented by another internal class named sun.reflection.Reflection which is basically browsing down the given number of call stack frames and then returns this method’s defining class. This security check is however likely to change in future version. When browsing the stack, the first found class (index 0) will obviously be the Reflection class itself, and the second (index 1) class will be the Unsafe class such that index 2 will hold your application class that was calling Unsafe#getUnsafe().

This looked-up class is then checked for its ClassLoader where a null reference is used to represent the bootstrap class loader on a HotSpot virtual machine. (This is documented in Class#getClassLoader() where it says that “some implementations may use null to represent the bootstrap class loader”.) Since no non-core Java class is normally ever loaded with this class loader, you will therefore never be able to call this method directly but receive a thrown SecurityException as an answer. (Technically, you could force the VM to load your application classes using the bootstrap class loader by adding it to the –Xbootclasspath, but this would require some setup outside of your application code which you might want to avoid.) Thus, the following test will succeed:

@Test(expected = SecurityException.class)
public void testSingletonGetter() throws Exception {
  Unsafe.getUnsafe();
}

However, the security check is poorly designed and should be seen as a warning against the singleton anti-pattern. As long as the use of reflection is not prohibited (which is hard since it is so widely used in many frameworks), you can always get hold of an instance by inspecting the private members of the class. From the Unsafe class's source code, you can learn that the singleton instance is stored in a private static field called theUnsafe. This is at least true for the HotSpot virtual machine. Unfortunately for us, other virtual machine implementations sometimes use other names for this field. Android’s Unsafe class is for example storing its singleton instance in a field called THE_ONE. This makes it hard to provide a “compatible” way of receiving the instance. However, since we already left the save territory of compatibility by using the Unsafe class, we should not worry about this more than we should worry about using the class at all. For getting hold of the singleton instance, you simply read the singleton field's value:

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

Alternatively, you can invoke the private instructor. I do personally prefer this way since it works for example with Android while extracting the field does not:

Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor();
unsafeConstructor.setAccessible(true);
Unsafe unsafe = unsafeConstructor.newInstance();

The price you pay for this minor compatibility advantage is a minimal amount of heap space. The security checks performed when using reflection on fields or constructors are however similar.

 

Create an instance of a class without calling a constructor


The first time I made use of the Unsafe class was for creating an instance of a class without calling any of the class's constructors. I needed to proxy an entire class which only had a rather noisy constructor but I only wanted to delegate all method invocations to a real instance which I did however not know at the time of construction. Creating a subclass was easy and if the class had been represented by an interface, creating a proxy would have been a straight-forward task. With the expensive constructor, I was however stuck. By using the Unsafe class, I was however able to work my way around it. Consider a class with an artificially expensive constructor:

class ClassWithExpensiveConstructor {

  private final int value;

  private ClassWithExpensiveConstructor() {
    value = doExpensiveLookup();
  }

  private int doExpensiveLookup() {
    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return 1;
  }

  public int getValue() {
    return value;
  }
}

Using the Unsafe, we can create an instance of ClassWithExpensiveConstructor (or any of its subclasses) without having to invoke the above constructor, simply by allocating an instance directly on the heap:

@Test
public void testObjectCreation() throws Exception {
  ClassWithExpensiveConstructor instance = (ClassWithExpensiveConstructor) 
  unsafe.allocateInstance(ClassWithExpensiveConstructor.class);
  assertEquals(0, instance.getValue());
}

Note that final field remained uninitialized by the constructor but is set with its type's default value. Other than that, the constructed instance behaves like a normal Java object. It will for example be garbage collected when it becomes unreachable.

The Java run time itself creates objects without calling a constructor when for example creating objects for deserialization. Therefore, the ReflectionFactory offers even more access to individual object creation:

@Test
public void testReflectionFactory() throws Exception {
  @SuppressWarnings("unchecked")
  Constructor<ClassWithExpensiveConstructor> silentConstructor = ReflectionFactory.getReflectionFactory()
      .newConstructorForSerialization(ClassWithExpensiveConstructor.class, Object.class.getConstructor());
  silentConstructor.setAccessible(true);
  assertEquals(10, silentConstructor.newInstance().getValue());
}

Note that the ReflectionFactory class only requires a RuntimePermission called reflectionFactoryAccess for receiving its singleton instance and no reflection is therefore required here. The received instance of ReflectionFactory allows you to define any constructor to become a constructor for the given type. In the example above, I used the default constructor of java.lang.Object for this purpose. You can however use any constructor:

class OtherClass {

  private final int value;
  private final int unknownValue;

  private OtherClass() {
    System.out.println("test");
    this.value = 10;
    this.unknownValue = 20;
  }
}

@Test
public void testStrangeReflectionFactory() throws Exception {
  @SuppressWarnings("unchecked")
  Constructor<ClassWithExpensiveConstructor> silentConstructor = ReflectionFactory.getReflectionFactory()
      .newConstructorForSerialization(ClassWithExpensiveConstructor.class,
            OtherClass.class.getDeclaredConstructor());
  silentConstructor.setAccessible(true);
  ClassWithExpensiveConstructor instance = silentConstructor.newInstance();
  assertEquals(10, instance.getValue());
  assertEquals(ClassWithExpensiveConstructor.class, instance.getClass());
  assertEquals(Object.class, instance.getClass().getSuperclass());
}

Note that value was set in this constructor even though the constructor of a completely different class was invoked. Non-existing fields in the target class are however ignored as also obvious from the above example. Note that OtherClass does not become part of the constructed instances type hierarchy, the OtherClass's constructor is simply borrowed for the "serialized" type.

Not mentioned in this blog entry are other methods such as Unsafe#defineClass, Unsafe#defineAnonymousClass or Unsafe#ensureClassInitialized. Similar functionality is however also defined in the public API's ClassLoader.

Native memory allocation


Did you ever want to allocate an array in Java that should have had more than Integer.MAX_VALUE entries? Probably not because this is not a common task, but if you once need this functionality, it is possible. You can create such an array by allocating native memory. Native memory allocation is used by for example direct byte buffers that are offered in Java's NIO packages. Other than heap memory, native memory is not part of the heap area and can be used non-exclusively for example for communicating with other processes. As a result, Java's heap space is in competition with the native space: the more memory you assign to the JVM, the less native memory is left.

Let us look at an example for using native (off-heap) memory in Java with creating the mentioned oversized array:

class DirectIntArray {

  private final static long INT_SIZE_IN_BYTES = 4;
  
  private final long startIndex;

  public DirectIntArray(long size) {
    startIndex = unsafe.allocateMemory(size * INT_SIZE_IN_BYTES);
    unsafe.setMemory(startIndex, size * INT_SIZE_IN_BYTES, (byte) 0);
    }
  }

  public void setValue(long index, int value) {
    unsafe.putInt(index(index), value);
  }

  public int getValue(long index) {
    return unsafe.getInt(index(index));
  }

  private long index(long offset) {
    return startIndex + offset * INT_SIZE_IN_BYTES;
  }

  public void destroy() {
    unsafe.freeMemory(startIndex);
  }
}

@Test
public void testDirectIntArray() throws Exception {
  long maximum = Integer.MAX_VALUE + 1L;
  DirectIntArray directIntArray = new DirectIntArray(maximum);
  directIntArray.setValue(0L, 10);
  directIntArray.setValue(maximum, 20);
  assertEquals(10, directIntArray.getValue(0L));
  assertEquals(20, directIntArray.getValue(maximum));
  directIntArray.destroy();
}

First, make sure that your machine has sufficient memory for running this example! You need at least (2147483647 + 1) * 4 byte = 8192 MB of native memory for running the code. If you have worked with other programming languages as for example C, direct memory allocation is something you do every day. By calling Unsafe#allocateMemory(long), the virtual machine allocates the requested amount of native memory for you. After that, it will be your responsibility to handle this memory correctly.

The amount of memory that is required for storing a specific value is dependent on the type's size. In the above example, I used an int type which represents a 32-bit integer. Consequently a single int value consumes 4 byte. For primitive types, size is well-documented. It is however more complex to compute the size of object types since they are dependent on the number of non-static fields that are declared anywhere in the type hierarchy. The most canonical way of computing an object's size is using the Instrumented class from Java's attach API which offers a dedicated method for this purpose called getObjectSize. I will however evaluate another (hacky) way of dealing with objects in the end of this section.

Be aware that directly allocated memory is always native memory and therefore not garbage collected. You therefore have to free memory explicitly as demonstrated in the above example by a call to Unsafe#freeMemory(long). Otherwise you reserved some memory that can never be used for something else as long as the JVM instance is running what is a memory leak and a common problem in non-garbage collected languages. Alternatively, you can also directly reallocate memory at a certain address by calling Unsafe#reallocateMemory(long, long) where the second argument describes the new amount of bytes to be reserved by the JVM at the given address.

Also, note that the directly allocated memory is not initialized with a certain value. In general, you will find garbage from old usages of this memory area such that you have to explicitly initialize your allocated memory if you require a default value. This is something that is normally done for you when you let the Java run time allocate the memory for you. In the above example, the entire area is overriden with zeros with help of the Unsafe#setMemory method.

When using directly allocated memory, the JVM will neither do range checks for you. It is therefore possible to corrupt your memory as this example shows:

@Test
public void testMallaciousAllocation() throws Exception {
  long address = unsafe.allocateMemory(2L * 4);
  unsafe.setMemory(address, 8L, (byte) 0);
  assertEquals(0, unsafe.getInt(address));
  assertEquals(0, unsafe.getInt(address + 4));
  unsafe.putInt(address + 1, 0xffffffff);
  assertEquals(0xffffff00, unsafe.getInt(address));
  assertEquals(0x000000ff, unsafe.getInt(address + 4));
}

Note that we wrote a value into the space that was each partly reserved for the first and for the second number. This picture might clear things up. Be aware that the values in the memory run from the "right to the left" (but this might be machine dependent).

The first row shows the initial state after writing zeros to the entire allocated native memory area. Then we override 4 byte with an offset of a single byte using 32 ones. The last row shows the result after this writing operation.

Finally, we want to write an entire object into native memory. As mentioned above, this is a difficult task since we first need to compute the size of the object in order to know the amount of size we need to reserve. The Unsafe class does however not offer such functionality. At least not directly since we can at least use the Unsafe class to find the offset of an instance's field which is used by the JVM when itself allocates objects on the heap. This allows us to find the approximate size of an object:

public long sizeOf(Class<?> clazz)
  long maximumOffset = 0;
  do {
    for (Field f : clazz.getDeclaredFields()) {
      if (!Modifier.isStatic(f.getModifiers())) {
        maximumOffset = Math.max(maximumOffset, unsafe.objectFieldOffset(f));
      }
    }
  } while ((clazz = clazz.getSuperclass()) != null);
  return maximumOffset + 8;
}

This might at first look cryptic, but there is no big secret behind this code. We simply iterate over all non-static fields that are declared in the class itself or in any of its super classes. We do not have to worry about interfaces since those cannot define fields and will therefore never alter an object's memory layout. Any of these fields has an offset which represents the first byte that is occupied by this field's value when the JVM stores an instance of this type in memory, relative to a first byte that is used for this object. We simply have to find the maximum offset in order to find the space that is required for all fields but the last field. Since a field will never occupy more than 64 bit (8 byte) for a long or double value or for an object reference when run on a 64 bit machine, we have at least found an upper bound for the space that is used to store an object. Therefore, we simply add these 8 byte to the maximum index and we will not run into danger of having reserved to little space. This idea is of course wasting some byte and a better algorithm should be used for production code.

In this context, it is best to think of a class definition as a form of heterogeneous array. Note that the minimum field offset is not 0 but a positive value. The first few byte contain meta information. The graphic below visualizes this principle for an example object with an int and a long field where both fields have an offset. Note that we do not normally write meta information when writing a copy of an object into native memory so we could further reduce the amount of used native memoy. Also note that this memory layout might be highly dependent on an implementation of the Java virtual machine.
With this overly careful estimate, we can now implement some stub methods for writing shallow copies of objects directly into native memory. Note that native memory does not really know the concept of an object. We are basically just setting a given amount of byte to values that reflect an object's current values. As long as we remember the memory layout for this type, these byte contain however enough information to reconstruct this object.

public void place(Object o, long address) throws Exception {
  Class clazz = o.getClass();
  do {
    for (Field f : clazz.getDeclaredFields()) {
      if (!Modifier.isStatic(f.getModifiers())) {
        long offset = unsafe.objectFieldOffset(f);
        if (f.getType() == long.class) {
          unsafe.putLong(address + offset, unsafe.getLong(o, offset));
        } else if (f.getType() == int.class) {
          unsafe.putInt(address + offset, unsafe.getInt(o, offset));
        } else {
          throw new UnsupportedOperationException();
        }
      }
    }
  } while ((clazz = clazz.getSuperclass()) != null);
}

public Object read(Class clazz, long address) throws Exception {
  Object instance = unsafe.allocateInstance(clazz);
  do {
    for (Field f : clazz.getDeclaredFields()) {
      if (!Modifier.isStatic(f.getModifiers())) {
        long offset = unsafe.objectFieldOffset(f);
        if (f.getType() == long.class) {
          unsafe.putLong(instance, offset, unsafe.getLong(address + offset));
        } else if (f.getType() == int.class) {
          unsafe.putLong(instance, offset, unsafe.getInt(address + offset));
        } else {
          throw new UnsupportedOperationException();
        }
      }
    }
  } while ((clazz = clazz.getSuperclass()) != null);
  return instance;
}

@Test
public void testObjectAllocation() throws Exception {
  long containerSize = sizeOf(Container.class);
  long address = unsafe.allocateMemory(containerSize);
  Container c1 = new Container(10, 1000L);
  Container c2 = new Container(5, -10L);
  place(c1, address);
  place(c2, address + containerSize);
  Container newC1 = (Container) read(Container.class, address);
  Container newC2 = (Container) read(Container.class, address + containerSize);
  assertEquals(c1, newC1);
  assertEquals(c2, newC2);
}

Note that these stub methods for writing and reading objects in native memory only support int and long field values. Of course, Unsafe supports all primitive values and can even write values without hitting thread-local caches by using the volatile forms of the methods. The stubs were only used to keep the examples concise. Be aware that these "instances" would never get garbage collected since their memory was allocated directly. (But maybe this is what you want.) Also, be careful when precalculating size since an object's memory layout might be VM dependent and also alter if a 64-bit machine runs your code compared to a 32-bit machine. The offsets might even change between JVM restarts.

For reading and writing primitives or object references, Unsafe provides the following type-dependent methods:
  • getXXX(Object target, long offset): Will read a value of type XXX from target's address at the specified offset.
  • putXXX(Object target, long offset, XXX value): Will place value at target's address at the specified offset.
  • getXXXVolatile(Object target, long offset): Will read a value of type XXX from target's address at the specified offset and not hit any thread local caches.
  • putXXXVolatile(Object target, long offset, XXX value): Will place value at target's address at the specified offset and not hit any thread local caches.
  • putOrderedXXX(Object target, long offset, XXX value): Will place value at target's address at the specified offet and might not hit all thread local caches.
  • putXXX(long address, XXX value): Will place the specified value of type XXX directly at the specified address.
  • getXXX(long address): Will read a value of type XXX from the specified address.
  • compareAndSwapXXX(Object target, long offset, long expectedValue, long value): Will atomicly read a value of type XXX from target's address at the specified offset and set the given value if the current value at this offset equals the expected value.
Be aware that you are copying references when writing or reading object copies in native memory by using the getObject(Object, long) method family. You are therefore only creating shallow copies of instances when applying the above method. You could however always read object sizes and offsets recursively and create deep copies. Pay however attention for cyclic object references which would cause infinitive loops when applying this principle carelessly.

Not mentioned here are existing utilities in the Unsafe class that allow manipulation of static field values sucht as staticFieldOffset and for handling array types. Finally, both methods named Unsafe#copyMemory allow to instruct a direct copy of memory, either relative to a specific object offset or at an absolute address as the following example shows:

@Test
public void testCopy() throws Exception {
  long address = unsafe.allocateMemory(4L);
  unsafe.putInt(address, 100);
  long otherAddress = unsafe.allocateMemory(4L);
  unsafe.copyMemory(address, otherAddress, 4L);
  assertEquals(100, unsafe.getInt(otherAddress));
}

Throwing checked exceptions without declaration


There are some other interesting methods to find in Unsafe. Did you ever want to throw a specific exception to be handled in a lower layer but you high layer interface type did not declare this checked exception? Unsafe#throwException allows to do so:

@Test(expected = Exception.class)
public void testThrowChecked() throws Exception {
  throwChecked();
}

public void throwChecked() {
  unsafe.throwException(new Exception());
}

Native concurrency


The park and unpark methods allow you to pause a thread for a certain amount of time and to resume it:

@Test
public void testPark() throws Exception {
  final boolean[] run = new boolean[1];
  Thread thread = new Thread() {
    @Override
    public void run() {
      unsafe.park(true, 100000L);
      run[0] = true;
    }
  };
  thread.start();
  unsafe.unpark(thread);
  thread.join(100L);
  assertTrue(run[0]);
}

Also, monitors can be acquired directly by using Unsafe using monitorEnter(Object), monitorExit(Object) and tryMonitorEnter(Object).

A file containing all the examples of this blog entry is available as a gist.