How many times have we seen programmers call System.gc() to "help the garbage collector"? Unfortunately far too often, with potentially terrible performance implications. In this newsletter we explore the explicit and the diagnostic GC and how we can force a GC, even if explicit GCs are disabled. Full Article
In this guest article by Kirk Pepperdine, we learn about how P99 latency is affected by garbage collection stop-the-world events. Full Article
JEP 254 replaced the char[] in our Strings with byte[]. How much memory does this save in our Strings? In this newsletter we show how we can determine this from a heap dump file. Full Article
Java has support for parallelism baked into the JDK. We have parallel streams, parallel sort and CompletableFutures, all using the same common ForkJoinPool. In this newsletter we explore how to measure the effectiveness of our parallelism. Full Article
Streams can make our code more readable, and therefore more maintainable. However, there is some overhead in setting up the stream, a cost that might become pronounced when the stream is empty. In this newsletter we will consider an idea of the EmptyStream to reduce that cost. Full Article
One of the most convenient ways of constructing complex Strings is with String.format(). It used to be excessively slow, but in Java 17 is about 3x faster. In this newsletter we discover what the difference is and where it will help you. Also when you should use format() instead of the plain Stri... Full Article
MethodHandles annotate the invoke() methods with @PolymorphicSignature. In this newsletter we see how this can help to avoid unnecessary object creation. Full Article
Each PrintStream uses about 25kb of memory. This might seem reasonable if we only have System.out and System.err. But what happens if we try create millions? And why do they use so much memory? Full Article
In our next puzzle, we up the ante a bit. We prevent GC during the test() method by storing a strong reference to all our Vectors. Cock and bull story, or are we struggling to identity our biases? Full Article
For today's puzzle, we are getting elements from Vector, sequentially and in parallel. But why is the performance so much worse in Java 15-ea+28? Full Article
How much memory was wasted when an additional boolean field was added to java.lang.String in Java 13? None at all. This article explains why. Full Article
In Java 2, the computational time complexity of String#hashCode() became linear, as it used every character to calculate the hash. Java 3 cached the hash code, so that it would not need to be recalculated every time we called hashCode(), except in the case that the hash code was zero. Java 13 fi... Full Article
When are Strings deduplicated? How can we find out whether they are of any benefit in our application? How much does it cost in terms of CPU? We try to show you how we can get this from the deduplication statistics provided by the JVM. Full Article
The Java Development Kit is filled with great examples of how design patterns can be used to make the Java code easier to maintain. But what is the performance impact of all this indirection and additional object creation? In this newsletter we explore how the compiler makes well-factored Java ... Full Article
Apparently Full GC is done in parallel in the Java 10 G1 collector. Or is it? In this newsletter we set out to discover the truth by dumping the GC CPU usage with the new Unified JVM Logging. Full Article
Just like inner classes, lambdas might also suffer from memory issues, but to a lesser extent. In this puzzle you need to figure out which lambdas are affected. Full Article
Java 6 introduced a mechanism to store ASCII characters inside byte[] instead of a char[]. This feature was removed again in Java 7. However, it is coming back in Java 9, except this time round, compaction is enabled by default and byte[] is always used. Full Article
BigInteger has new algorithms for multiplying and dividing large numbers that have a better computational complexity than previous versions of Java. A further improvement would be to parallelize multiply() with Fork/Join. Full Article
Java 8 HashMap has been optimized to avoid denial of service attacks with many distinct keys containing identical hash codes. Unfortunately performance might degrade if you use your own keys. In this newsletter we show a tool that you can use to inspect your HashMap and view the key distributio... Full Article
Lambdas are often described as anonymous inner classes without the boilerplate code. However, lambdas are more powerful. Firstly, a lambda does not always result in a new object. Secondly, "this" refers to the outer object. Thirdly, a lambda object can implement multiple interfaces. In this ... Full Article
Even though standard Java is not real-time, we often use it in time-sensitive applications. Since GC events are often the reason for latency outliers, such code seeks to avoid allocation. In this newsletter we look at some tools to add to your unit tests to check your allocation limits. Full Article
Heavily contended concurrent constructs may benefit from a small pause after a CAS failure, but this may lead to worse performance if we do more work in between each update attempt. In this follow-up newsletter, we show how adding CPU consumption can change our performance characteristics. Full Article
What is faster? Synchronized or Atomic compare-and-set? In this newsletter we look at some surprising results when we run Java on the new i7 chip. Full Article
In this newsletter, we present a little performance puzzler, written by Kirk Pepperdine. What is happening with this system? There is only one explanation and it can be discovered by just looking at the stack trace. Full Article
In this newsletter we measure the memory requirements of various types of hash maps available in Java. Maps usually need to be threadsafe, but non-blocking is not always the most important requirement. Full Article
The garbage collector can cause our program to slow down at inappropriate times. In this newsletter we look at how we can delay the GC to never run and thus produce reliable results. Then, instead of actually collecting the dead objects, we simply shut down and start again. Full Article
Many years ago, when hordes of C++ programmers ventured to the greener pastures of Java, some strange myths were introduced into the language. It was said that a "try" was cheaper than an "if" - when nothing went wrong. Full Article
What has a larger serializable size, ArrayList or LinkedList? In this newsletter we examine what the difference is and also why Vector is a poor candidate for a list in a serializable class. Full Article
In this newsletter, we show how the Generator described in our previous issue can be used to create virtual proxy classes statically, that is, by generating code instead of using dynamic proxies. Full Article
In this newsletter, we have a look at how we can create new classes in memory and then inject them into any class loader. This will form the basis of a system to generate virtual proxies statically. Full Article
Escape analysis can make your code run 110 times faster - if you are a really really bad programmer to begin with :-) In this newsletter we look at some of the places where escape analysis can potentially help us. Full Article
In this newsletter, we reveal the answer to the puzzle from last month and explain the reasons why the first class sometimes fails and why the second always succeeds. Remember this for your next job interview ... Full Article
In this newsletter we show you a puzzle, where a simple request causes memory to be released, that otherwise could not. Solution will be shown in the next newsletter. Full Article
It is well known that implementing a non-trivial finalize() method can cause GC and performance issues, plus some subtle concurrency bugs. In this newsletter, we show how we can find all objects with a non-trivial finalize() method, even if they are not currently eligible for finalization. Full Article
In this newsletter, we show two approaches for listening to bytes on sockets. The first uses the Delegator from our previous newsletter, whereas the second uses AspectJ to intercept the call to Socket.getInput/OutputStream. We also write an MBean to publish this information in JConsole. Full Article
In this newsletter we examine what happens when a ReadWriteLock is swamped with too many reader or writer threads. If we are not careful, we can cause starvation of the minority in some versions of Java. Full Article
Prior to Java 1.4, ThreadLocals caused thread contention, rendering them useless for performant code. In the new design, each thread contains its own ThreadLocalMap, thus improving throughput. However, we still face the possibility of memory leaks due to values not being cleared out of the Thre... Full Article
In this newsletter, we reveal some of the polymorphism mysteries in the JDK. The HotSpot Server Compiler can distinguish between mono-morphism, bi-morphism and poly-morphism. The bi-morphism is a special case which executes faster than poly-morphism. Mono-morphism can be inlined by the compile... Full Article
Late binding is supposed to be a bottleneck in applications - this was one of the criticisms of early Java. The HotSpot Compiler is however rather good at inlining methods that are being called through polymorphism, provided that we do not have very many implementation subclasses. Full Article
Memory usage of Java objects has been a mystery for many years. In this newsletter, we use the new instrumentation API to predict more accurately how much memory an object uses. Based on earlier newsletters, but revised for Java 5 and 6. Full Article
With Java 5, we can measure CPU cycles per thread. Here is a small program that runs several CPU intensive tasks in separate threads and then compares the elapsed time to the total CPU time of the threads. The factor should give you some indication of the CPU based acceleration that the multi c... Full Article
As developers we often hear that performance often comes at the price of good design. However when we have our performance tuning hats on, we often find that good design is essential to help achieve good performance. In this article we will explore one example of where a good design choice has be... Full Article
When we query the database using EJB3, the Query object returns an untyped collection. In this newsletter we look at several approaches for safely converting this to a typed collection. Full Article
Java level monitor deadlocks used to be hard to find. Then along came JDK 1.4 and showed them in CTRL+Break. In JDK 5, we saw the addition of the ThreadMXBean, which made it possible to continually monitor an application for deadlocks. However, the limitation was that the ThreadMXBean only wor... Full Article
In this newsletter we look at the difference in performance between cloning and copying an array of bytes. Beware of the Microbenchmark! We also show how misleading such a test can be, but explain why the cloning is so much slower for small arrays. Full Article
A few weeks ago, I tried to demonstrate the effects of old vs. new generation GC. The results surprised me and reemphasized how important GC is to your overall program performance. Full Article
ArrayList is faster than LinkedList, except when you remove an element from the middle of the list. Or is it? Full Article
Java 5 has some interesting performance optimizations than can make our code faster without our intervention. We look at some of the new features. Full Article
Soft and weak references allow us to control how long objects stay live if they do not have strong references to them. Weak references can help us avoid memory leaks by breaking circular dependencies. Soft references can help us cache objects, recreating them when running low on memory. Full Article
Since Java 5, we have a JVM system thread constantly monitoring our memory usage. If we exceed our specified threshold, it will send us a notification. We can use this to get an early warning of possible trouble. Full Article
We look at the new Java 5 features: Generics, autoboxing and the for-in statement. It should make our code more maintainable without sacrificing performance. Full Article
Object streams maintain caches on the input and output. This helps with avoiding StackOverflowError when we have circular references. It also saves bandwidth if we transmit the same objects several times. However, this can also cause a memory leak. Full Article
Our old MemoryCounter needed to be updated for Java 1.4. In previous versions of Java, each primitive field used at least 4 bytes, even a boolean. This changed in Java 1.4, where boolean and byte use a 1 byte, short and char use 2 bytes, int and float use 4 and long and double use 8. Full Article
We have a look at the creation cost of multi-dimensional arrays in Java. Full Article
Multi-dimensional arrays in Java are simply arrays of arrays. This can have consequences in CPU and memory performance. Full Article
Quick update on the results of the last survey. Only 15.53% knew the correct answer! Full Article
We look at the difference in bytecode between using ints and bytes. We also compare a += b and the longer a = a + b. They are not equivalent. Full Article
Java compilers convert Strings appended with + to StringBuffer. The generated bytecode is compiler specific, with javac and the Eclipse compiler producing slightly different results. Full Article
Before running a microbenchmark, it can be instructive to examine the code using a tool javap. This shows us the bytecode of the compiled class. Full Article
The Singleton pattern allows for a single instance to be shared throughout the program. The question we will answer is how to initialize this. Full Article
For years, programmers have spread the misinformation that it was necessary to set local variables to null to avoid memory leaks. Fortunately Java is smart enough to do that without our help. Full Article
In this follow-up to our earlier newsletter on "When arguments get out of hand...", we look at the constant pool in Java classes and how this can be affected by how we compile our class. Full Article
We turn the dial to full blast and find out how many parameters a method may contain. Wholly impractical, but fun. Full Article
By specifying our own RMISocketFactory, we can monitor the number of bytes that are transmitted over RMI. Full Article
The "remainder function" is a form of division. "Division" is the most expensive CPU operation. HotSpot can transform "remainder" to a cheaper "multiply" operation. When benchmarking, we need to make sure that the divisor is not constant. Full Article
One of the most significant changes in JDK 1.4 is regarding how the HashMap works internally. Instead of the remainder function, it now uses bit masking to assign keys to buckets. This change has implications on how we write our hashCode() method. Full Article
In Java 1.4, they added some cool new features. First off, toString() in collections was improved to avoid a StackOverflowError, secondly the RandomAccess interface was introduced and lastly, the JavaDocs were improved to also contain specifications of what unchecked exceptions to expect. Full Article
Java has some interesting ways in which we can invert a boolean value. We compare the speed of various approaches. Full Article
In this newsletter, we modify the class Object to secretly count how many of each class are constructed. Full Article
A few questions came up in our previous newsletter, so here is a follow-up with answers. Full Article
ArrayList can become slow when used as a FIFO queue. Whenever an element is removed from the head, the other elements need to be moved one space to the left. This is an O(n) operation and slows down the remove(0) operation the longer the list becomes. In this newsletter we describe a CircularA... Full Article
If we were to use a List as a Queue, which would be better: ArrayList or LinkedList? Turns out that it depends on the length of the list. In this newsletter we try write a self-tuning queue, which swaps over to a suitable implementation based on the number of current elements. Full Article
Prior to Java NIO, we needed one thread per socket. In this newsletter we show how we can use timeouts on the sockets to simulate something like non-blocking IO. Full Article
In the days before BlockingQueue was added to Java, we had to write our own. This newsletter describes an approach using synchronized and wait()/notify(). Full Article
We all know WeakHashMap, which has WeakReferences to the keys and strong references to the values. In this class we instead have SoftReferences to the keys. This means that entries will typically be removed once we get low on memory, rather when there are no more references to the keys. Full Article
Java deadlocks can be tricky to discover. In this very first Java Specialists' Newsletter, we look at how to diagnose such an error and some techniques for solving it. Full Article
Get: every new article, exclusive invites to live webinars, our top-10 articles ever, access to expert tutorials & more!
Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.
We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations. Find Out More