The Java Memory Model (JMM) defines the behavior of the memory system in a multi-threaded environment. It specifies the rules for reading and writing to shared memory locations, and ensures that threads communicate with each other in a safe and predictable manner. However, sometimes the JMM rules can be too strict and can affect performance. In such cases, the JMM annotations can be used to relax some of these rules, without sacrificing correctness.
The JMM annotations were introduced in Java 8 and provide a way to annotate code to indicate that it relies on certain memory consistency guarantees. These annotations are:
@Contended: This annotation is used to mark a class or field that may be subject to false sharing. False sharing occurs when multiple threads access different fields that are located on the same cache line, which can result in excessive cache invalidations and reduce performance. The
@Contended annotation helps to prevent false sharing by instructing the JVM to place the annotated object in a separate cache line.
@sun.misc.Contended: This annotation is similar to @Contended but is used for backward compatibility with older versions of Java.
@sun.misc.ContendedWeak: This annotation is used to mark a field that may be subject to false sharing, but the object that contains the field is not long-lived. This annotation is weaker than @Contended, and may not be supported by all JVMs.
@sun.misc.Signal: This annotation is used to declare a signal handler method. Signal handlers are used to handle signals sent to the JVM by the operating system, such as SIGTERM or SIGINT.
@sun.misc.Cleaner: This annotation is used to mark a method that should be called when an object is garbage-collected. The annotated method should have a void return type and take no arguments.
Example usage of @Contended annotation:
import java.util.concurrent.atomic.AtomicLong;
public class ContendedDemo {
@sun.misc.Contended
private final AtomicLong counter = new AtomicLong(0);
public long getCounter() {
return counter.get();
}
public void incrementCounter() {
counter.incrementAndGet();
}
}
In this example, the @Contended annotation is used to mark the counter field as potentially subject to false sharing. The annotation tells the JVM to place the counter field in a separate cache line, which can improve performance.
Itβs important to note that the JMM annotations are not part of the Java specification and may not be supported by all JVMs. Therefore, itβs recommended to test the performance of annotated code on different JVM implementations before deploying it to production.