这是一个非常奇特的案例,似乎是一个.class文件损坏。我们的应用程序取决于其他团队提供的依赖性。有2个相关的java文件:FTGService
和FTGServiceLight implements FTGService
。
所以当我javap -p FTGService
打印时:
....
public abstract java.util.List<munshi.transfers.domain.TransferredFile> getArchivedFilesByLastSyncTime(java.util.Date, java.util.Date, java.util.Date, java.util.Date, java.util.Date, java.util.List<java.lang.String>, java.util.List<java.lang.Integer>);
在执行javap -p FTGServiceLight
时,会打印:
....
public java.util.List<munshi.transfers.domain.TransferredFile> getArchivedFilesByLastSyncTime(java.util.Date, java.util.Date, java.util.Date, java.util.Date, java.util.Date, java.util.List<java.lang.String>, java.util.List<java.lang.Integer>);
....
当我javap -v FTGServiceLight
时,可以找到相关信息here。
但是在运行它时会抛出一个错误:
出于某种原因,java.lang.AbstractMethodError: munshi.transfers.service.light.FTGServiceLight.getArchivedFilesByLastSyncTime(Ljava / UTIL /日期; Ljava / util的/日期; Ljava / util的/日期; Ljava / util的/日期; Ljava / util的/日期; Ljava / util的/列表; Ljava / UTIL /列表)Ljava / util的/列表; 在 broker.services.resolver.impl.FileSyncServiceImpl.fetchFiles(FileSyncServiceImpl.java:71) 在 broker.services.resolver.impl.TransferFileSync.run(TransferFileSync.java:71) 在sun.reflect.GeneratedMethodAccessor129.invoke(未知来源)
getArchivedFilesByLastSyncTime
被标记为abstract
。此外,当我调试它时,这就是它在执行时所显示的内容:
FTGServiceLight.getMethod("getArchivedFilesByLastSyncTime",Date.class,Date.class,Date.class,Date.class,Date.class, List.class, List.class))
注意modifiers
显示为1025
,而Modifiers.isAbstract(1025)
返回true
。因此,调试方法getArchivedFilesByLastSyncTime
显示为abstract
,但javap
则另有说明。但是当我反编译FTGServiceLight
时,它确实显示了方法body,所以它似乎被覆盖了。
可能导致此行为的原因
PS:我已经检查了mvn依赖树,这个类的替代版本从未出现过。
答案 0 :(得分:2)
它看起来确实是一个多重依赖性问题。只检查Maven依赖树并不能确保您在运行时没有同一个类的多个版本。
它可以被缓存,可以从不同的地方加载等。在FileSyncServiceImpl中,尝试打印出加载FTGServiceLight的位置:
System.out.println(
FTGServiceLight.class.getClassLoader().getResource(
FTGServiceLight.class.getName().replace('.', '/') + ".class"));
并与使用此类的上下文进行比较:
System.out.println(
FileSyncServiceImpl.class.getClassLoader().getResource(
FileSyncServiceImpl.class.getName().replace('.', '/') + ".class"));
它是同一个classlaoder吗?
您可以尝试的另一件事是检查类加载器用于加载类的位置。在FileSyncServiceImpl中执行:
System.out.print(
Arrays.toString(((URLClassLoader)
Test1.class.getClassLoader()).getURLs()));
它将为您提供此类加载器所在的jar文件(和目录)列表。然后,您可以检查FTGServiceLight是否位于其中任何一个以及是否多次出现。