标记为抽象但javap未显示的方法

时间:2015-12-31 13:01:12

标签: java jvm javac bytecode

这是一个非常奇特的案例,似乎是一个.class文件损坏。我们的应用程序取决于其他团队提供的依赖性。有2个相关的java文件:FTGServiceFTGServiceLight 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))

enter image description here

注意modifiers显示为1025,而Modifiers.isAbstract(1025)返回true。因此,调试方法getArchivedFilesByLastSyncTime显示为abstract,但javap则另有说明。但是当我反编译FTGServiceLight时,它确实显示了方法body,所以它似乎被覆盖了。

可能导致此行为的原因

PS:我已经检查了mvn依赖树,这个类的替代版本从未出现过。

1 个答案:

答案 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是否位于其中任何一个以及是否多次出现。