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。
我正在尝试在服务器完成启动之前对服务器的某些 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。