Minborg

Minborg
Minborg
Showing posts with label JVM. Show all posts
Showing posts with label JVM. Show all posts

Friday, December 16, 2016

Day 16, Java Holiday Calendar 2016, Hacking Java Classes

16. Hacking the Existing Java Classes



Today's tips is about hacking the existing Java classes. But before we start, I would like to issue a disclaimer: I am only showing this to illustrate certain possibilities. This post contains code that  is against best-practice and also a number of license terms for commercial JVMs and I would discourage anyone from using this for purposes other than just experimenting in dark cellars at late nights.

The Task

There is a lot of magic going around with auto-boxing and instance caching with wrapper classes like java.lang.Integer. Suppose we could hack the Integer class so it will keep track of how many of its instances are created and how many instances are garbage collected and that we could add a way of retrieving this statistics in some form? How do we go about?

Open Sesame

The JVM has a command line parameter named "-Xbootclasspath/p:" that can be used to load Java classes before the standard java classes are loaded. This way, we can inject our own versions of Java classes before the real ones are loading.

This is useful also for other classes that are not a part of the standard Java library. If there is a bug in a third party product, we can correct the bug and just load the correct version before the app loads. It also enables us to instrument classes so they, for example, can collect usage statistics or introduce or prevent certain things from happening.

Hacking the Integer class

Create a custom class named Integer and place that in a package named java.lang. Retrieve the standard source code of Integer form the JDK and copy that into the custom java.lang.Integer class.

Add the following at the beginning of the copied Integer class:

    public static final AtomicLong INSTANCE_CREATE_COUNTER = new AtomicLong();
    public static final AtomicLong INSTANCE_FINALIZE_COUNTER = new AtomicLong();

Modify the constructor like this:

    public Integer(int value) {
        this.value = value;
        INSTANCE_CREATE_COUNTER.incrementAndGet();
    }

Finally, add the following method:

    @Override
    protected void finalize() throws Throwable {
        INSTANCE_FINALIZE_COUNTER.incrementAndGet();
    }

That's it! We have hacked the Integer class. The modified class can now be used like this:

package org.darkside.hack;

public class Main {

    public static void main(String[] args) {

        printIntegerInstanceInfo();
        Integer i = 456;
        printIntegerInstanceInfo();
        System.gc();
        sleep(1000);
        printIntegerInstanceInfo();

    }

    public static void printIntegerInstanceInfo() {
        long create = Integer.INSTANCE_CREATE_COUNTER.get();
        long finalized = Integer.INSTANCE_FINALIZE_COUNTER.get();
        System.out.format(
            "The JVM has created %d instances and finalized %d instances of Integer."
                + " Thus, %d instances are on the heap.%n",
            create,
            finalized,
            create - finalized
        );
    }

    public static void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException ie) {

        }
    }

}

Running the Code

The code can be run like this:

java -Xbootclasspath/p:hack_java_class-1.0.0-SNAPSHOT.jar org.darkside.hack.Main

We have to change the name of the .jar file depending how we named our artifact. Make sure that the modified Integer class and the Main class resides in the same jar. We can also have the modified classes in a separate jar but then we need to add the other parts using the normal class path commands.

Wrap up

The notion here is "Don't Try This at Home". That said, we can learn a lot by injecting custom classes into the JVM.

There are many better ways of keeping track of how many instances that are created and destroyed by the JVM. The task in this post is just for the sake of reasoning.

Be careful out there!





Thursday, December 15, 2016

Day 15, Java Holiday Calendar 2016, Don't Optimize Now!

15. Don't Optimize Now!





Today's tips is about how the JVM can optimize our code. Back in the good ol' Java 1.0 days, I remember running programs that replaced the names of variables, classes and methods so they would become shorter, presumably resulting in faster execution. When things blew up in our faces, we were clueless what really happened because the NPE that method c threw in class D that inherited from class A just didn't provide adequate information as to what really went wrong. It was better before.... not...

These days, the present JVM is just incredible improved over its first incarnations. The JVM will collect statistics on how methods are used and then use that piece of information when it eventually will compile the method with its Just-In-Time (JIT) compiler. This often takes place when a method has been called for about 10 000 times. This is one reason why we should "warm up" our code properly before we run benchmarks.

The JVM is also using a scheme called Code Flattening which means that it is able to "roll up" method calls and consider the code as a larger flow of operations. This way, it is able to determine the possible paths the program can take and consider these paths individually and optimize them. For example, identical range checking that takes place in several methods that call each other can be eliminated. Another example is that dead paths (e.g. where an "if"-branch is using a constant expression) can be eliminated all together.

Another means of optimization is Escape Analysis that is used to determine if an object is visible outside a certain scope. If not, the object can be allocated on the stack rather then on the heap making the program run much faster. Consider the following code snippet:

    @Override 
    public String toString() {
      final StringBuilder sb = new StringBuilder()
        .append("(")
        .append(x)
        .append(", ")
        .append(y)
        .append(")");
      return sb.toString();
  }

Once this code is compiled and when the method has been called a predetermined number of times, the JVM will allocate the StringBuilder on the stack rather than on the heap. Once the method returns, the StringBuilder is cleaned up automatically when the stack is popped upon its return. Because the object cannot be observed from outside, it is also possible to use a simplified representation of the StringBuilder on the stack. So, effectively, the StringBuilder never exists and thus putting in a lot of work to eliminate it is waisted work and will only result in code that looks bad.

One cool thing is that the JVM can combine its optimization schemes. For example, with code flattening, much larger scopes can be used for escape analysis and objects that actually do escape a method might be re-catch on a higher "rolled up" level. Such objects may be subject to stack allocation too. Amazing stuff! 

There are two golden rules when it comes to optimization:

1) Don't optimize
2) Don't optimize now...

That said, when we want to write performance critical applications, it is important to have a basic understanding of the JVM to really know what is going on under the hood. Sometimes it really pays of to rewrite and optimize code.

Speedment, an open-source stream ORM tool and runtime, relies on a number of JVM features to be able to provide efficient execution of its own and application Java code. In particular, the stream implementations benefit substantially from code flattening and escape analysis.

Know your JVM an put your effort where it matters and not in places the JVM will optimize anyhow.

Follow the Java Holiday Calendar 2016 with small tips and tricks all the way through the winter holiday season.



Thursday, January 14, 2016

Be Lazy with Java 8

Background

One of the most distinguished feature of us programmers is that we are inherently lazy. Not in a bad way that we do not want to work, but in a better way: We do not want to do the same thing twice and we do not want to do it at all if we do not have to. In fact, not writing code is often the better alternative in the cases you can reuse something else instead.

The same thing is true for our applications. Often, we want them to be lazy so that they only do what is absolutely necessary and nothing more.

I have used the Lazy class presented here in the open-source project Speedment that makes database applications really short and concise.

Read more on how we can make our applications lazy in this post.

Implementing Lazy Initialization

In this post, the goal is to show a Lazy class that can be used for objects with a relatively long life expectancy and where there might be any number of calls (from zero to the millions) to a particular method. We must also ensure that the class is thread safe. Lastly, we want to have maximum performance for different threads calling the class many times.

Here is the proposed class:

public final class Lazy<T> {

    private volatile T value;

    public T getOrCompute(Supplier<T> supplier) {
        final T result = value;  // Read volatile just once...
        return result == null ? maybeCompute(supplier) : result;
    }

    private synchronized T maybeCompute(Supplier<T> supplier) {
        if (value == null) {
            value = requireNonNull(supplier.get());
        }
        return value;
    }

}


The Lazy class can be used in many applications. Immutable classes are especially good candidates for lazy initialization. For example, Java's built-in String class employs lazy initialization in its hashCode() method. Here is one example how we can use the Lazy class:
public class Point {

    private final int x, y;
    private final Lazy<String> lazyToString;

    public Point(int x, int y) {
        this.x = x; 
        this.y = y;
        lazyToString = new Lazy<>();
    }

    @Override
    public String toString() {
        return lazyToString.getOrCompute( () -> "(" + x + ", " + y + ")");
    }

}

Looking back on the Lazy class again, we see that it only contains a single “holder” field for its value (I will explain why the field is not declared volatile later on) (EDIT: the field must be volatile to guarantee our requirements). There is also a public method getOrCompute() that allows us to retrieve the value. This method also takes a Supplier that will be used if and only if the value has not been set previously. The Supplier must produce a non-null value. Note the use of a local variable result, allowing us to reduce the number of volatile reads from two to one where the Lazy instance has been initialized already. Before I explain the features of this particular implementation, we need to revisit the Java Memory Model and particularly variable visibility across threads. If you want, you can skip the next chapter and just accept that Lazy works as it supposed to do. However, I do encourage you to read on.

The Java Memory Model and Visibility

One of the key issues with the Java Memory Model is the concept of visibility. If Thread 1 updates a variable someValue = 2 then when would the other threads (e.g. Thread 2) see this update? It turns out that Thread 1’s update will not be seen immediately by other threads. In fact, there is no guarantee as to how quickly a change in this variable will be seen by other threads at all. It could be 100 ns, 1 ms, 1 s or even 10 years in theory. There are performance reasons for isolating the java memory view between threads. Because each thread can have its own memory view, the level of parallelism will be much higher than if threads were supposed to share and guarantee the same memory model.

Some of the benefits with relaxed visibility are that it allows:

  • The compiler to reorder instructions in order to execute more efficiently
  • The compiler to cache variables in CPU registers
  • The CPU to defer flushing of writes to main memory
  • Old entries in reading processors’ caches to be used

The Java keywords final, synchronized and volatile allows us to change the visibility of objects across threads. The Java Memory Model is quite a big topic and perhaps I will write a more elaborate post on the issue later on. However, in the case of synchronization, a thread that enters a synchronization block must invalidate its local memory (such as CPU registers or cache entries that involves variables inside the synchronization block) so that reads will be made directly from main memory. In the same way, a thread that exists a synchronization block must flush all its local memory. Because only one thread can be in a synchronization block at any given time, the effect is that all changes to variables are effectively visible to all threads that enters the synchronization block. Note that threads that do not enter the synchronization block does not have any visibility guarantee.

Also, If a field is declared volatile, reads and writes are always made via main memory and in order. Thus, updates to the field are seen by other threads at the cost of performance.

Properties of the Lazy Class

The field value is declared volatile and in the previous chapter we just learned that there are guarantees for visibility in that case and also, more importantly, guarantees of exact timing and in-order execution. So, if Thread 1 calls the Supplier and sets the value, Thread 2 might not see the update. If so, Thread 2 will enter the maybeCompute() method and because it is synchronized it will now, in fact, see Thread 1's update and it will see that the value was already set. From now on, Thread 2 will have a correct view of the value and it will never enter the synchronization block again. This is good if Thread 2 is expected to call the Lazy class many times. If another Thread 3 is created much later, it will most likely see the correct value from the beginning and we avoid synchronization altogether. So, for medium to long lived objects, this scheme is a win! We get thread isolation with no synchronization overhead.

When Are Lazy Appropriate to Use?

Lazy is a good choice if we want to defer calculation to a later time and we do not want to repeat the calculation. If we, on the other hand, know in advance that our toString() method is always going to be called many times, then we would not use the Lazy class. Instead, we could just calculate the toString() value once and for all eagerly in the constructor and store its value for later re-use.

Conclusion

The Lazy class is a very simple, yet powerful means of deferred calculation and a nice tool for performance optimization. The Lazy performs exceptionally well under the circumstances it was constructed for, with no thread synchronization overhead whatsoever for medium and long lived objects.

The Lazy class, as shown, is used in the open-source project Speedment in a number of applications including SQL rendering where, for example, the columns for a table remains the same during the JVM lifetime. Speedment is a tool that allows access to databases using standard Java 8 streams.

Be lazy and “steal” the Lazy class here so that your applications can be lazy too...