On Mon, 5 Aug 2024 00:32:40 GMT, leo liang <d...@openjdk.org> wrote:

> Hi there, we are seeing this issue when we run JFR on our services under 
> load, we see a large spike of CPU after JFR is triggered, which cause 500 
> errors in our service. We are currently using corretto-17 in our service.
> 
> Wondering this fix get back ported to JDK 17? As I can't find this change 
> mentioned in [JDK 
> update](https://wiki.openjdk.org/display/JDKUpdates/Archived+Releases) or in 
> [jdk17u tag 
> compare](https://github.com/openjdk/jdk17u/compare/jdk-17.0.9+9...jdk-17.0.13+1)
> 
> Also, wondering if there is a walk around for this issue if the PR is not 
> back ported to Java 17. `XX:+EnableDynamicAgentLoading` seems to only 
> supported in Java 21, so that wouldn't help for now

@leomao10, I'm not sure if this change will ever be downported to older 
releases like JDK 21 or even JDK 17. I personally consider it low risk, but 
there have been reports of performance regressions in some cases (e.g. 
[JDK-8336805](https://bugs.openjdk.org/browse/JDK-8336805)). I couldn't 
reproduce them, but I can image that they will make the maintainers of LTS 
releases even more cautious.

The easiest way to workaround this issue in JDK 17 would be to set the 
`can_redefine_classes`, `can_retransform_classes` or 
`can_generate_breakpoint_events` JVMTI capabilities at startup or early in the 
lifetime of the JVM. There are several ways how you could do this.
- trigger JFR right after startup. This will still invalidate all the JIT 
compiled methods but if you do this early enough there won'T be many of them. 
After you've triggered JFR for the first time, the corresponding JVMTI 
capabilities will be set and all dependencies will be recorded automatically so 
any subsequent JFR invocation won't suffer from a performance degradation any 
more.
- attach any other JVMTI agent like for example [async 
profiler](https://github.com/async-profiler/async-profiler) which requests the 
corresponding JVMTI capabilities at startup.
- write your own, trivial JVMTI agent which merely requests the corresponding 
JVMTI capabilities and attach it at startup with `agentpath:jvmtiAgent.so`. The 
agent can be as simple as:

/*

g++ -fPIC -shared -I $JAVA_HOME/include/ -I $JAVA_HOME/inlude/linux -o 
jvmtiAgent.so jvmtiAgent.cpp
 */

#include <jvmti.h>
#include <stdio.h>
#include <string.h>

extern "C"
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* jvm, char* options, void* reserved) 
{
  jvmtiEnv* jvmti = NULL;
  jvmtiCapabilities capa;
  jvmtiError error;

  jint result = jvm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_1);
  if (result != JNI_OK) {
    fprintf(stderr, "Can't access JVMTI!\n");
    return JNI_ERR;
  }

  memset(&capa, 0, sizeof(jvmtiCapabilities));
  capa.can_redefine_classes = 1;
  capa.can_retransform_classes = 1;
  capa.can_generate_breakpoint_events = 1;
  if (jvmti->AddCapabilities(&capa) != JVMTI_ERROR_NONE) {
    fprintf(stderr, "Can't set capabilities!\n");
    return JNI_ERR;
  } else {
    fprintf(stdout, "Added capabilities!\n");
  }
  return JNI_OK;
}

-------------

PR Comment: https://git.openjdk.org/jdk/pull/17509#issuecomment-2346646666

Reply via email to