Contextual (Java SE 26 & JDK 26)
Description: declaration: module: jdk.jfr, package: jdk.jfr, annotation type: Contextual
Keywords: jdk.jfr.Contextual class

# Annotation Interface Contextual

@Retention(RUNTIME) @Target(FIELD) public @interface Contextual
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;
    }

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;
    }

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
         ...
       ]
      }

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