本文作者:suxingrui
本文链接:https://blog.youkuaiyun.com/suxingrui/article/details/80114768
版权声明:本文为原创文章,转载请注明出处。
如题,在使用Java Agent过程中发现,agent JAR文件定义的manifest属性中的Boot-Class-Path配置成目录时无效。
虽然官方说明是支持目录的:
Boot-Class-Path
A list of paths to be searched by the bootstrap class loader. Paths represent directories or libraries (commonly referred to as JAR or zip libraries on many platforms). …详见
但尝试多次之后发现,确实无效。追踪溯源,只能去怼源码,顺便记录下调查过程。
调查基于JDK8、JDK8、JDK8!
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {// agent加载入口
...
/*
* If the Boot-Class-Path attribute is specified then we process
* each relative URL and add it to the bootclasspath.
*/
bootClassPath = getAttribute(attributes, "Boot-Class-Path");
if (bootClassPath != NULL) {
appendBootClassPath(agent, jarfile, bootClassPath);
}
...
}
static void
appendBootClassPath( JPLISAgent* agent,
const char* jarfile,
const char* pathList ) {
...
// 循环遍历path:pathList,查找path下的jar文件,添加到bootstrap class loader
jvmtierr = (*jvmtienv)->AddToBootstrapClassLoaderSearch(jvmtienv, path);
...
}
jvmtiError
JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) {// 查找实现
...
// create the zip entry
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
if (zip_entry == NULL) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
...
} /* end AddToBootstrapClassLoaderSearch */
// Create a class path zip entry for a given path (return NULL if not found
// or zip/JAR file cannot be opened)
ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
// check for a regular file
struct stat st;
if (os::stat(path, &st) == 0) {
if ((st.st_mode & S_IFREG) == S_IFREG) {// S_IFREG 表示一般文件
...
}
}
return NULL;
}
嗯,很好。只支持文件!
刚好看到create_class_path_zip_entry方法上面的create_class_path_entry(应该对应的是Class-Path的配置,待查)
包含以下逻辑
} else {
// Directory
new_entry = new ClassPathDirEntry(path);
if (TraceClassLoading) {
tty->print_cr("[Path %s]", path);
}
}
所以呢,官方也有好些坑等人去填。