43 多个相同限定名类型同时存在导致的继承结构混乱的情况

news/2024/5/8 10:13:53/文章来源:https://blog.csdn.net/u011039332/article/details/120936752

前言

 // 四刷天府绿道 

呵呵 在前面文章中 jetty-runner:jar:9.3.20 和 tomcat-embed-core-8.5.29 的 JarScannerCallback 不兼容, 导致服务启动失败 

提到了这样的一个问题 

我们再看一下这里的 callback 的接口, jetty-runner 的这个对象里面是没有 void scan(Jar jar, String webappPath, boolean isWebapp), 抛出了异常 

当然 假设 jetty-runner 里面 JarScannerCallback 有这个方法, 又会不会出现问题呢?, 我们单开一篇文章讨论 

呵呵 这里就是来看这里的问题 

当然本文需要对 invokeXX 指令的执行过程有一定的了解, 如下文章 也许有帮助   

方法调用的流程(invokestatic为例)

invoke static/special/virtual/interface

测试用例

UserService 接口 

package com.hx.test;/*** UserService** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2021-10-24 15:47*/
public interface UserService {String updateUser(String username, String password);String removeUser(String username, String password);}

测试用例

package com.hx.test;/*** Test00MultiClasspathSaveClass** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2021-10-24 15:46*/
public class Test00MultiClasspathSaveClass {// Test00MultiClasspathSaveClasspublic static void main(String[] args) {UserService userService = new UserServiceFactory().newUserService();userService.updateUser("xxx", "xx");userService.removeUser("xxx", "xx");}}

另外还需要另外一个包 : UserAddUpdate.jar 

里面存放的是 另外的一个 UserService 和 UserServiceImpl 

package com.hx.test;public interface UserService {String addUser(String var1, String var2);String updateUser(String var1, String var2);
}

package com.hx.test;public class UserServiceImpl implements UserService {public UserServiceImpl() {}public String addUser(String username, String password) {System.out.println("UserServiceImpl[addUser/updateUser] -> addUser");return username;}public String updateUser(String username, String password) {System.out.println("UserServiceImpl[addUser/updateUser] -> updateUser");return username;}
}

package com.hx.test;public class UserServiceFactory {public UserServiceFactory() {}public UserService newUserService() {return new UserServiceImpl();}
}

然后执行 用例, 会发现报错如下  

粘贴一下 主要测试用例的字节码信息 

master:classes jerry$ javap -v -c com/hx/test/Test00MultiClasspathSaveClass.class 
Classfile /Users/jerry/IdeaProjects/HXCase/target/classes/com/hx/test/Test00MultiClasspathSaveClass.classLast modified Oct 24, 2021; size 800 bytesMD5 checksum 56f3e1f6bc90419599e855b9992cd33eCompiled from "Test00MultiClasspathSaveClass.java"
public class com.hx.test.Test00MultiClasspathSaveClassminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref          #10.#26        // java/lang/Object."<init>":()V#2 = Class              #27            // com/hx/test/UserServiceFactory#3 = Methodref          #2.#26         // com/hx/test/UserServiceFactory."<init>":()V#4 = Methodref          #2.#28         // com/hx/test/UserServiceFactory.newUserService:()Lcom/hx/test/UserService;#5 = String             #29            // xxx#6 = String             #30            // xx#7 = InterfaceMethodref #31.#32        // com/hx/test/UserService.updateUser:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;#8 = InterfaceMethodref #31.#33        // com/hx/test/UserService.removeUser:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;#9 = Class              #34            // com/hx/test/Test00MultiClasspathSaveClass#10 = Class              #35            // java/lang/Object#11 = Utf8               <init>#12 = Utf8               ()V#13 = Utf8               Code#14 = Utf8               LineNumberTable#15 = Utf8               LocalVariableTable#16 = Utf8               this#17 = Utf8               Lcom/hx/test/Test00MultiClasspathSaveClass;#18 = Utf8               main#19 = Utf8               ([Ljava/lang/String;)V#20 = Utf8               args#21 = Utf8               [Ljava/lang/String;#22 = Utf8               userService#23 = Utf8               Lcom/hx/test/UserService;#24 = Utf8               SourceFile#25 = Utf8               Test00MultiClasspathSaveClass.java#26 = NameAndType        #11:#12        // "<init>":()V#27 = Utf8               com/hx/test/UserServiceFactory#28 = NameAndType        #36:#37        // newUserService:()Lcom/hx/test/UserService;#29 = Utf8               xxx#30 = Utf8               xx#31 = Class              #38            // com/hx/test/UserService#32 = NameAndType        #39:#40        // updateUser:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;#33 = NameAndType        #41:#40        // removeUser:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;#34 = Utf8               com/hx/test/Test00MultiClasspathSaveClass#35 = Utf8               java/lang/Object#36 = Utf8               newUserService#37 = Utf8               ()Lcom/hx/test/UserService;#38 = Utf8               com/hx/test/UserService#39 = Utf8               updateUser#40 = Utf8               (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;#41 = Utf8               removeUser
{public com.hx.test.Test00MultiClasspathSaveClass();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 10: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       5     0  this   Lcom/hx/test/Test00MultiClasspathSaveClass;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=3, locals=2, args_size=10: new           #2                  // class com/hx/test/UserServiceFactory3: dup4: invokespecial #3                  // Method com/hx/test/UserServiceFactory."<init>":()V7: invokevirtual #4                  // Method com/hx/test/UserServiceFactory.newUserService:()Lcom/hx/test/UserService;10: astore_111: aload_112: ldc           #5                  // String xxx14: ldc           #6                  // String xx16: invokeinterface #7,  3            // InterfaceMethod com/hx/test/UserService.updateUser:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;21: pop22: aload_123: ldc           #5                  // String xxx25: ldc           #6                  // String xx27: invokeinterface #8,  3            // InterfaceMethod com/hx/test/UserService.removeUser:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;32: pop33: returnLineNumberTable:line 15: 0line 16: 11line 17: 22line 19: 33LocalVariableTable:Start  Length  Slot  Name   Signature0      34     0  args   [Ljava/lang/String;11      23     1 userService   Lcom/hx/test/UserService;
}
SourceFile: "Test00MultiClasspathSaveClass.java"

问题的分析

以上用例执行 classpath 为 : /Users/jerry/IdeaProjects/HXCase/target/classes:/Users/jerry/IdeaProjects/HXCase/target/artifacts/UserAddUpdate/UserAddUpdate.jar

大致可以理出程序中使用的 UserService 是 updateUser + removeUser 所在的 UserService, 所以 用例能够正常编译通过 

然后 new UserServiceFactory().newUserService() 获取到的实例为 UserServiceImpl, 继承自 addUser + updateUser 所在的 UserService 

如果你看过 上面提到的两篇文章, 应该能够想到这个结果 是为什么 

Test00MultiClasspathSaveClass 中创建了 UserServiceImpl 的实例, 并调用了 updateUser + removeUser 所在的 UserService 的 updateUser 方法 

"invokeinterface #7, 3" 对应的是 Test00MultiClasspathSaveClass 中常量池中第七个元素, 是一个 InterfaceMethodRef 

在 invokeinterface 的时候, 发现对应的 cacheEntry 尚未被解析, 于是开始解析 #7, 将符号引用替换为直接引用(解析是通过 name 和 signature 来进行匹配的) 

解析 #7 的时候, updateUser + removeUser 所在的 UserService 中有 updateUser(String, String), 并且 UserServiceImpl 中有 updateUser(String, String), 解析成功, 然后调用的是 UserServiceImpl 的 updateUser(String, String) 

同理解析 #8 的时候 updateUser + removeUser 所在的 UserService 中有 removeUser(String, String), 并且 UserServiceImpl 中没有有 removeUser(String, String) 

然后 vm 的理解是 UserServiceImpl 实现了 updateUser + removeUser 所在的 UserService 的接口, 但是又没有重写 removeUser(String, String) 方法, 抛出了 AbstractMethodError 

调整classpath的顺序

假设我们吧 UserAddUpdate.jar 的依赖放在前面, 那么我们 UserService 是 addUser + updateUser 的 UserService, UserServiceImpl 继承自 addUser + updateUser 的 UserService 

但是 Test00MultiClasspathSaveClass 中还有一个 removeUser(String, String) 的一个 invokeinterface, 看一下 会有怎么样的效果 

invokeinterface #7 和上面同理 

同理解析 #8 的时候 addUser + updateUser 所在的 UserService 中没有有 removeUser(String, String) 

然后有需要调用 addUser + updateUser 所在的 UserService 的 removeUser(String, String), 因此 直接抛出了 NoSuchMethodError 

cmd 中调用 Test00MultiClasspathSaveClass, 调整 classpath 的不同的效果 

master:UserAddUpdate jerry$ java -classpath "/Users/jerry/IdeaProjects/HXCase/target/classes:/Users/jerry/IdeaProjects/HXCase/target/artifacts/UserAddUpdate/UserAddUpdate.jar" com.hx.test.Test00MultiClasspathSaveClass
UserServiceImpl[addUser/updateUser] -> updateUser
Exception in thread "main" java.lang.AbstractMethodError: com.hx.test.UserServiceImpl.removeUser(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;at com.hx.test.Test00MultiClasspathSaveClass.main(Test00MultiClasspathSaveClass.java:17)master:UserAddUpdate jerry$ java -classpath "/Users/jerry/IdeaProjects/HXCase/target/artifacts/UserAddUpdate/UserAddUpdate.jar:/Users/jerry/IdeaProjects/HXCase/target/classes" com.hx.test.Test00MultiClasspathSaveClass
UserServiceImpl[addUser/updateUser] -> updateUser
Exception in thread "main" java.lang.NoSuchMethodError: com.hx.test.UserService.removeUser(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;at com.hx.test.Test00MultiClasspathSaveClass.main(Test00MultiClasspathSaveClass.java:17)

本问题在一般的新项目中不会出现, 但是 在一些老项目, 或者 依赖相当多, 相当杂的情况下 是有可能出现的, 遇到问题的时候不要慌, 看一下本文的理解 

参考 

方法调用的流程(invokestatic为例)

invoke static/special/virtual/interface

jetty-runner:jar:9.3.20 和 tomcat-embed-core-8.5.29 的 JarScannerCallback 不兼容, 导致服务启动失败 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_401966.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【附源码】计算机毕业设计SSM民宿短租系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

JavaEE - Servlet(向服务器上传文件 Part类)

我们在需要向服务器上传文件时&#xff0c;在前端需要使用form表单&#xff0c;form表单需要使用特殊的类型 form-data 此时提交文件的时候&#xff0c;浏览器会把文件内容以form-data的格式构造到HTTP请求中&#xff0c;服务器就可以通过getPart获取了 需要注意&#xff1a;…

2.idea 标定相关

1.发现 VINS对于参数准确性的要求高于ORBSLAM。依据是相同的参数,ORBSLAM可以提供准确的定位结果,但是VINS很容易就会发散。在线标定外参很有效,经历过几次外参标定以后的外参给VINS可以获得很好的效果,但是不排除只是针对这个场景,随后测试如果效果好,考虑给ORBSLAM3增加…

Redis常见的问题

① 缓存雪崩 缓存雪崩是指在短时间内&#xff0c;有⼤量缓存同时过期&#xff0c;导致⼤量的请求直接查询数据库&#xff0c;从⽽对数据库造成 了巨⼤的压⼒&#xff0c;严重情况下可能会导致数据库宕机的情况叫做缓存雪崩。 我们先来看下正常情况下和缓存雪崩时程序的执⾏流…

docker安装tomcat、mysql、redis

一、tomcat 1.下载tomcat8docker pull tomcat:8.5.612.启动容器(-d 后台启动)docker run -d -p 8080:8080 tomcat:8.5.61 3.访问首页http://ip:8080/访问不到 404 解决:需要修改tomcat下的文件夹 如下 进入后webapps.dist改为webapps 二、mysql 1.拉取mysqldocker pull mys…

网课题搜答案公众号接口系统

网课题搜答案公众号接口系统 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xf…

分布式数据库的基本概念

1.分布式数据库系统的产生和定义 产生原因: 经济的发展&#xff1a;经济发展&#xff1a;跨国公司&#xff1a;产生一个地方需要管理另外一个地方数据的需求 发展历程&#xff1a; 20世纪70年代末 成长于80年代 第一个数据库系统SDD-1是美国计算机公司(CAA)于1976年-1978年…

浏览器插件官方demo学习(一):基本代码、页面渲染、书签、cookie、Omnibox等

前言 参考&#xff1a;https://github.com/GoogleChrome/chrome-extensions-samples 官方目前只提供了几个基于v3版本的例子&#xff0c;其他例子都是基于v2版本的&#xff08;可能是官方比较忙&#xff0c;没空写例子吧&#xff09;。先从v3版本的例子开始学习&#xff0c;后…

JVM(六) —— 运行时数据区之堆的详细介绍(一)

JVM&#xff08;六&#xff09; —— 运行时数据区之虚拟机栈的详细介绍核心概述堆空间代码演示堆空间划分&#xff08;重要&#xff09;一个Java程序运行起来是一个进程&#xff0c;这个进程对应着一个JVM实例&#xff0c;一个JVM实例对应着一个运行时数据区。而一个运行时数据…

JAVA设计模式-组合模式

目录 1、例子 2、组合模式基本定义 总结&#xff1a; 1、例子 编写程序展示一个学校院系结构&#xff1a;需求是这样&#xff0c;要在一个页面中展示出学校的院系 组成&#xff0c;一个学校有多个学院&#xff0c;一个学院有多个系传统解决方案&#xff1a; 分析&#xff1a;…

一起学solidity写智能合约——整型(uint和int)

前言 整型一般用的比较多&#xff0c;会在各个合约中见到整型的存在&#xff0c;那么这个类型也是学习路上不可或缺的 环境&#xff1a; remix编译器点我跳转 正文 我们在sol中遇得到很多类型为整型的数据&#xff0c;所以我们的sol提供了两种数据类型的整型&#xff1a; …

基于物联网的户外环境检测装置设计

目 录 摘 要 1 Abstract 2 第1章 绪论 4 1.2 选题背景及意义 4 1.2 研究现状 4 1.3本课题的发展趋势和研究可行性 5 1.4研究主要内容 5 第2章 基于物联网的户外环境检测装置设计概述和相关原理 6 2.1 系统的概述 6 2.1.1 总体设计方案 6 2.1.2 总体框图 6 2.2 相关理论 7 2.2.1…

算法优化 | MATLAB实现BO-RF贝叶斯优化随机森林算法

算法优化 | MATLAB实现BO-RF贝叶斯优化随机森林算法 目录 算法优化 | MATLAB实现BO-RF贝叶斯优化随机森林算法效果一览基本介绍模型结构程序设计学习总结参考资料效果一览 基本介绍 针对集成学习参数众多,缺乏高效准确的参数寻优方法的问题,提出了基于贝叶斯优化随机森林方法…

k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

RK3588+AI工业视觉检测设计方案

本文详细介绍了基于Rockchip RK3588芯片的AI边缘计算主板外形、尺寸、技术规格&#xff0c;以及详细的硬件接口设计参考说明&#xff0c;使客户可以快速将RK3588边缘计算主板应用于工业互联网、智慧城市、智慧安防、智慧交通&#xff0c;智慧医疗等人工智能领域的智能终端设备。…

自定义ClassLoader

一&#xff0c;如何自定义classLoader&#xff1f; 需要使用加载器的loadClass方法&#xff1a;ClassLoader().loadClass 查看loadClass方法源码 首先检查加载&#xff0c;调用父5加载器开始双亲委派机制&#xff0c; 如果没有加载到&#xff0c;就调用findClass方式 打开发现…

JVM加载class文件的原理机制

JVM加载class文件的原理机制 JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的&#xff1b; 当Java程序需要使用某个类时&#xff0c;JVM会确 保这个类已经被加载、连接(验证、准备和解析)和初始化。 类的加载是指把类的.class文件中的数据 读入到内存中&#xff0c…

神经网络中各个隐藏层,深度神经网络隐藏层数

1、神经网络的隐含层节点数怎么设置啊&#xff1f;比如要设置18层隐含节点数&#xff01;跪求&#xff0c;工作急用&#xff01; 隐层一般是一层或两层&#xff0c;很少会采用三层以上&#xff0c;至少隐层的节点数确定&#xff0c;一般有以下几种方法&#xff1a;1、有经验的…

【ArchSummit】通过ArchSummit 全球架构师峰会对企业数字化转型的思考

前言 &#x1f4eb; 作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &a…

生命在于学习——Socket编程(偏安全方面)

本篇文章仅用于学习记录和交流&#xff0c;不得用于其他违规用途&#xff0c;产生的不良后果&#xff0c;自己负责。 一、Socket介绍 首先socket (套接字) 是工作在应用层和传输层之间一个抽像层 , 为什么要有他呢 ? 虽然我们已经有了ipport可以和世界上任意一台计算机上的软…