class 在预加载期间再次加载一次应用程序的其余部分 运行

Does a class loaded once during premain load again once the rest of the application run

我正在尝试在服务器完成启动之前对服务器的某些 classes 进行检测,因为我需要监视它的某些活动。在这种情况下,我使用的是带有 premain 方法的 javaagent。此代理加载任何必需的 classes 并使用 Instrumentation 接口的 retransformClasses 对它们进行检测。

我 100% 确定我正在尝试在服务器中检测 运行 的 class,因为我之前通过遍历所有 class 检测了相同的 class =30=]es 由服务器加载。由于这会增加服务器启动时的开销,我一直在尝试改用上述方法。当我 运行 在应用程序服务器之外时,它工作得很好。但是当我尝试在服务器上 运行 它时,检测部分的执行没有任何异常或检测所需的 classes 和方法。但是当应用程序在服务器上启动时,我没有从检测方法中获得任何输出。

(例如,假设我正在尝试检测 org.h2.jdbc.JdbcPreparedStatement class 的 executeQuery 方法。我必须将 h2 jar 添加到 class 路径)

下面的代码段描述了 premain 方法,该方法用于使用 retransformClass 方法加载每个 class:

for (InstrumentationClass instrumentationClass : instrumentationClasses){
  Class currentClass = ClassLoader.getSystemClassLoader()
                                  .loadClass(instrumentationClass.getClassName());
  SchemaClass currentClassWithDetails = new SchemaClass(
      scenario.getScenarioName(), currentClass, instrumentationClass);
  InstrumentationClassTransformer.transformMe.add(currentClassWithDetails);
  instrumentation.retransformClasses(currentClass);
  InstrumentationClassTransformer.transformMe.remove(currentClassWithDetails);
}

是否可能在服务器的其余部分启动时加载相同 class 的不同副本?有办法克服这个问题吗?

应用程序服务器通常使用子优先 class 加载器将应用程序与应用程序服务器的代码隔离开来。这样,可以简单地删除应用程序服务器的 class 加载程序,以便在不重新启动 JVM 的情况下取消部署应用程序。

A Java 代理访问 classes 通过系统 ClassLoader 保持对服务器应用程序 classes 的引用。因此,对于不同的 class 加载程序,org.h2.jdbc.JdbcPreparedStatement 可能存在两次 - 系统和应用程序 class 加载程序 - 您只检测已部署的应用程序中未使用的加载程序。

不过,我确实想知道您的方法有何意义。为什么不能只安装 ClassFileTransformer 并在加载 class 后检查名称是否为 org/h2/jdbc/JdbcPreparedStatement 和仪器。开销不应该太大。这样,您将为任何 class 装载程序检测 class,并且您还会在重新部署时重新检测 classes。