APIdia Launch Partner
Top Description Methods
jdk.jfr

public @Interface Contextual

extends Annotation
Annotations
@MetadataDefinition
@Label:Context
@Retention:RUNTIME
@Target:FIELD
Imports
java.lang.annotation.ElementType, .Retention, .RetentionPolicy, .Target

Event field annotation, specifies that the value carries contextual information.

Contextual information is data that applies to all events happening in the same thread from the beginning to the end of the event with a field annotated with Contextual.

For example, to trace requests or transactions in a system, a trace event can be created to provide context.

@Label("Trace") @Name("com.example.Trace") class TraceEvent extends Event { @Label("ID") @Contextual String id; @Label("Name") @Contextual String name; }
@Label("Trace")
@Name("com.example.Trace")
class TraceEvent extends Event {
    @Label("ID")
    @Contextual
    String id;

    @Label("Name")
    @Contextual
    String name;
}

To track details within an order service, an order event can be created where only the order ID provides context.

@Label("Order") @Name("com.example.Order") class OrderEvent extends Event { @Label("Order ID") @Contextual long id; @Label("Order Date") @Timestamp(Timestamp.MILLISECONDS_SINCE_EPOCH) long date; @Label("Payment Method") String paymentMethod; }
@Label("Order")
@Name("com.example.Order")
class OrderEvent extends Event {
    @Label("Order ID")
    @Contextual
    long id;

    @Label("Order Date")
    @Timestamp(Timestamp.MILLISECONDS_SINCE_EPOCH)
    long date;

    @Label("Payment Method")
    String paymentMethod;
}

If an order in the order service stalls due to lock contention, a user interface can display contextual information together with the JavaMonitorEnter event to simplify troubleshooting, for example:

$ jfr print --events JavaMonitorEnter recording.jfr jdk.JavaMonitorEnter { Context: Trace.id = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01" Context: Trace.name = "POST /checkout/place-order" Context: Order.id = 314159 startTime = 17:51:29.038 (2025-02-07) duration = 50.56 ms monitorClass = java.util.ArrayDeque (classLoader = bootstrap) previousOwner = "Order Thread" (javaThreadId = 56209, virtual = true) address = 0x60000232ECB0 eventThread = "Order Thread" (javaThreadId = 52613, virtual = true) stackTrace = [ java.util.zip.ZipFile$CleanableResource.getInflater() line: 685 java.util.zip.ZipFile$ZipFileInflaterInputStream.<init>(ZipFile) line: 388 java.util.zip.ZipFile.getInputStream(ZipEntry) line: 355 java.util.jar.JarFile.getInputStream(ZipEntry) line: 833 ... ] }
$ jfr print --events JavaMonitorEnter recording.jfr
jdk.JavaMonitorEnter {
  Context: Trace.id = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
  Context: Trace.name = "POST /checkout/place-order"
  Context: Order.id = 314159
  startTime = 17:51:29.038 (2025-02-07)
  duration = 50.56 ms
  monitorClass = java.util.ArrayDeque (classLoader = bootstrap)
 previousOwner = "Order Thread" (javaThreadId = 56209, virtual = true)
 address = 0x60000232ECB0
 eventThread = "Order Thread" (javaThreadId = 52613, virtual = true)
 stackTrace = [
   java.util.zip.ZipFile$CleanableResource.getInflater() line: 685
   java.util.zip.ZipFile$ZipFileInflaterInputStream.<init>(ZipFile) line: 388
   java.util.zip.ZipFile.getInputStream(ZipEntry) line: 355
   java.util.jar.JarFile.getInputStream(ZipEntry) line: 833
   ...
 ]
}

The difference between Relational and Contextual annotations is that Relational ties event data together to form a global data structure, similar to a foreign key in a relational database, but Contextual represents a state that applies to all events that happen at the same time, in the same thread. A field can be both contextual and relational at the same time.

A contextual field may incur overhead on a parser reading a recording file, since it must track active context, so it should be used sparingly and only where appropriate.

Since
25

Method Summary

Inherited from java.lang.annotation.Annotation:
annotationTypeequalshashCodetoString