gpt4 book ai didi

java - 如何在运行时找出类的来源?

转载 作者:行者123 更新时间:2023-11-30 09:04:26 24 4
gpt4 key购买 nike

我遇到了一个奇怪的问题,来自某些传递依赖项的类在运行时不断出现,从(正确的)第一级依赖项中隐藏了该类的更新版本,即使我认为我确保我排除了来 self 声明的所有其他依赖项的旧版本(这是在 Maven/IntelliJ 设置中)

更具体地说,在运行时,应用程序因 NoClassDefFoundError 而失败,因为在类加载期间加载了错误版本的所属类,该类的字段类型在较新版本中不存在该类在其中定义的库的名称。为了说明:

// lib.jar:wrong-version
class Owner {
private SomeType f;
}

// lib.jar:new-version
class Owner {
private OtherType f;
}

在运行时,类加载器找到对符号 Owner 的引用,并尝试加载具有 SomeType 的版本,而后者不再存在。即使我排除了 wrong-version 我能发现的地方也是如此。

我还运行了 mvn dependency:tree 来查看旧版本是否仍在某处被拉入,但事实并非如此!

为了进一步调试它,我想知道是否有办法找出类加载器从哪里读取特定类,即哪个文件?那可能吗?或者甚至更好,构建一个定义了特定符号的起源列表,以防它被定义多次?

抱歉,如果这含糊不清,但问题相当模糊。

最佳答案

以下代码将在整个类路径中搜索特定类。如果没有参数,它将转储它找到的每个类,然后您可以通过管道传递给 grep 或重定向到一个文件。它看起来在 jar 里...

用法:WhichClassWhichClass package.name(注意没有.class)

抱歉缺少评论...

import java.io.File;
import java.io.IOException;

import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public final class WhichClass {

private WhichClass() {
}

static Vector<String> scratchVector;

public static void main(final String[] argv) {
Vector v;

if ((argv.length == 0) || "-all".equals(argv[0])) {
v = findClass(null);
} else {
v = findClass(argv[0]);
}

for (int i = 0; i < v.size(); i++) {
System.out.println(v.elementAt(i));
}
}

static String className(final String classFile) {
return classFile.replace('/', '.').substring(0, classFile.length() - ".class".length());
}

static Vector findClass(final String className) {
if (className != null) {
scratchVector = new Vector<String>(5);
} else {
scratchVector = new Vector<String>(5000);
}

findClassInPath(className, setupBootClassPath());
findClassInPath(className, setupClassPath());

return scratchVector;
}

static void findClassInPath(final String className, final StringTokenizer path) {
while (path.hasMoreTokens()) {
String pathElement = path.nextToken();

File pathFile = new File(pathElement);

if (pathFile.isDirectory()) {
try {
if (className != null) {
String pathName = className.replace('.', System.getProperty("file.separator").charAt(0)) + ".class";

findClassInPathElement(pathName, pathElement, pathFile);
} else {
findClassInPathElement(className, pathElement, pathFile);
}
} catch (IOException e) {
e.printStackTrace();
}
} else if (pathFile.exists()) {
try {
if (className != null) {
String pathName = className.replace('.', '/') + ".class";

ZipFile zipFile = new ZipFile(pathFile);
ZipEntry zipEntry = zipFile.getEntry(pathName);
if (zipEntry != null) {
scratchVector.addElement(pathFile + "(" + zipEntry + ")");
}
} else {
ZipFile zipFile = new ZipFile(pathFile);
Enumeration entries = zipFile.entries();

while (entries.hasMoreElements()) {
String entry = entries.nextElement().toString();

if (entry.endsWith(".class")) {
String name = className(entry);

scratchVector.addElement(pathFile + "(" + entry + ")");
}
}
}
} catch (IOException e) {
System.err.println(e + " while working on " + pathFile);
}
}
}
}

static void findClassInPathElement(final String pathName, final String pathElement, final File pathFile)
throws IOException {
String[] list = pathFile.list();

for (int i = 0; i < list.length; i++) {
File file = new File(pathFile, list[i]);

if (file.isDirectory()) {
findClassInPathElement(pathName, pathElement, file);
} else if (file.exists() && (file.length() != 0) && list[i].endsWith(".class")) {
String classFile = file.toString().substring(pathElement.length() + 1);

String name = className(classFile);

if (pathName != null) {
if (classFile.equals(pathName)) {
scratchVector.addElement(file.toString());
}
} else {
scratchVector.addElement(file.toString());
}
}
}
}

static StringTokenizer setupBootClassPath() {
String classPath = System.getProperty("sun.boot.class.path");
String separator = System.getProperty("path.separator");

return new StringTokenizer(classPath, separator);
}

static StringTokenizer setupClassPath() {
String classPath = System.getProperty("java.class.path");
String separator = System.getProperty("path.separator");

return new StringTokenizer(classPath, separator);
}
}

关于java - 如何在运行时找出类的来源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25216687/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com