Class DevLoopAgent

java.lang.Object
com.vaadin.flow.devloop.agent.DevLoopAgent

public final class DevLoopAgent extends Object
Captures the Instrumentation handle at JVM startup and publishes it, so the in-app dev-loop connector can perform atomic class redefinitions in-process.

The daemon jar carries Premain-Class/Agent-Class pointing here alongside its own Main-Class, so one artifact is both the runnable daemon and the javaagent the application JVM loads. Only this class is ever loaded into the application JVM.

The handle is published two ways, so the connector finds it regardless of which class loader ends up owning the application classes: as a static field here (which works when the agent jar is visible to the application loader, the normal case since agent jars are appended to the system class path), and as a value in the system properties table, which is a Hashtable<Object, Object> and can therefore carry an arbitrary object - that path needs no class visibility at all.

Depends on nothing but java.instrument: it is loaded before the application, into a JVM whose class path it must not influence.

For internal use only. May be renamed or removed in a future release.

  • Field Details

    • PROPERTY

      public static final String PROPERTY
      The system properties key the Instrumentation handle used to be published under.

      It is no longer written. The system properties table is a Hashtable<Object, Object> and will hold an arbitrary object, which is what made it a convenient way to hand the handle across class loaders - but a table that is declared to map strings to strings and does not is a trap for everything else in the JVM that reads it. Measured against WildFly 38: Narayana merges the system properties when it loads jbossts-properties.xml, took the handle for a string, and the transactions subsystem failed its boot operations with a NullPointerException - fatally, after the HTTP listener had already bound. The handle now travels by get() instead.

      Kept only so that a reader who finds the name in an older log or an older dev server can see what became of it.

      See Also:
  • Method Details

    • premain

      public static void premain(String args, Instrumentation inst)
      Entry point when the agent is loaded at JVM startup with -javaagent:.
      Parameters:
      args - the agent arguments, unused
      inst - the instrumentation handle to publish
    • agentmain

      public static void agentmain(String args, Instrumentation inst)
      Entry point when the agent is attached to a running JVM.
      Parameters:
      args - the agent arguments, unused
      inst - the instrumentation handle to publish
    • get

      public static Instrumentation get()
      The captured instrumentation handle, or null when this class was loaded without the agent having been installed.

      This is the one channel. A -javaagent jar is appended to the system class path, so this class is the system class loader's and its static is the same object for every loader beneath it - including a servlet container's, which is the case the system-properties table was once used for. A caller that cannot name the class directly, because the agent jar is not on its own class path, reaches it through ClassLoader.getSystemClassLoader(); see the dev server's DevLoopRedefiner.

      Returns:
      the instrumentation handle, or null