标记为抽象但未由 javap 显示的方法
Method marked as abstract but not shown by javap
这是一个非常特殊的案例,似乎是 .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/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/List;Ljava/util/List;)Ljava/util/List;
at
broker.services.resolver.impl.FileSyncServiceImpl.fetchFiles(FileSyncServiceImpl.java:71)
at
broker.services.resolver.impl.TransferFileSync.run(TransferFileSync.java:71)
at sun.reflect.GeneratedMethodAccessor129.invoke(Unknown Source) at
getArchivedFilesByLastSyncTime
由于某种原因被标记为 abstract
。此外,当我调试它时,这就是它在执行时显示的内容:
FTGServiceLight.getMethod("getArchivedFilesByLastSyncTime",Date.class,Date.class,Date.class,Date.class,Date.class, List.class, List.class))
注意 modifiers
显示为 1025
并执行 Modifiers.isAbstract(1025)
returns true
。因此调试方法 getArchivedFilesByLastSyncTime
显示为 abstract
但 javap
以其他方式建议。但是我反编译FTGServiceLight
的时候确实显示了body这个方法,所以好像是被覆盖了
可能导致此行为的原因
PS:我检查了 mvn 依赖树,这个 class 的替代版本从来没有出现过。
看起来确实是一个多重依赖问题。仅检查 Maven 依赖关系树并不能确保您在运行时没有相同 class 的多个版本。
它可以被缓存,可以从不同的地方加载,等等。在 FileSyncServiceImpl 中,尝试打印出 FTGServiceLight 的加载位置:
System.out.println(
FTGServiceLight.class.getClassLoader().getResource(
FTGServiceLight.class.getName().replace('.', '/') + ".class"));
并与使用此 class 的上下文进行比较:
System.out.println(
FileSyncServiceImpl.class.getClassLoader().getResource(
FileSyncServiceImpl.class.getName().replace('.', '/') + ".class"));
是一样的吗class老大?
您可以尝试的另一件事是检查 classloader 从哪些位置加载 classes。在 FileSyncServiceImpl 中执行:
System.out.print(
Arrays.toString(((URLClassLoader)
Test1.class.getClassLoader()).getURLs()));
它将为您提供此 classloader 所在的 jar 文件(和目录)的列表。然后,您可以检查 FTGServiceLight 是否位于其中任何一个中,以及它是否多次出现。
这是一个非常特殊的案例,似乎是 .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/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/List;Ljava/util/List;)Ljava/util/List; at broker.services.resolver.impl.FileSyncServiceImpl.fetchFiles(FileSyncServiceImpl.java:71) at broker.services.resolver.impl.TransferFileSync.run(TransferFileSync.java:71) at sun.reflect.GeneratedMethodAccessor129.invoke(Unknown Source) at
getArchivedFilesByLastSyncTime
由于某种原因被标记为 abstract
。此外,当我调试它时,这就是它在执行时显示的内容:
FTGServiceLight.getMethod("getArchivedFilesByLastSyncTime",Date.class,Date.class,Date.class,Date.class,Date.class, List.class, List.class))
注意 modifiers
显示为 1025
并执行 Modifiers.isAbstract(1025)
returns true
。因此调试方法 getArchivedFilesByLastSyncTime
显示为 abstract
但 javap
以其他方式建议。但是我反编译FTGServiceLight
的时候确实显示了body这个方法,所以好像是被覆盖了
可能导致此行为的原因
PS:我检查了 mvn 依赖树,这个 class 的替代版本从来没有出现过。
看起来确实是一个多重依赖问题。仅检查 Maven 依赖关系树并不能确保您在运行时没有相同 class 的多个版本。
它可以被缓存,可以从不同的地方加载,等等。在 FileSyncServiceImpl 中,尝试打印出 FTGServiceLight 的加载位置:
System.out.println(
FTGServiceLight.class.getClassLoader().getResource(
FTGServiceLight.class.getName().replace('.', '/') + ".class"));
并与使用此 class 的上下文进行比较:
System.out.println(
FileSyncServiceImpl.class.getClassLoader().getResource(
FileSyncServiceImpl.class.getName().replace('.', '/') + ".class"));
是一样的吗class老大?
您可以尝试的另一件事是检查 classloader 从哪些位置加载 classes。在 FileSyncServiceImpl 中执行:
System.out.print(
Arrays.toString(((URLClassLoader)
Test1.class.getClassLoader()).getURLs()));
它将为您提供此 classloader 所在的 jar 文件(和目录)的列表。然后,您可以检查 FTGServiceLight 是否位于其中任何一个中,以及它是否多次出现。