报LinkageError的原因(1)

LinkageError是一个比较棘手的异常,准确的说它是一个Error而不是Exception。java api对它没有直接的解释,而是介绍了它的子类:

    Subclasses of LinkageError indicate that a class has some dependency on another class; however, the latter class has incompatibly changed after the compilation of the former class.

似乎是说不兼容性,既编译时,A类用到B类,且这时候A和B是兼容的,但是到运行时,A类得到的B(既某个类加载器加载的B类)却不是A在编译的时候那个与之兼容的B,这个说起来比较复杂,其实就是个二进制兼容性问题,和很多程序不能在98上跑是一个道理,程序就是A,而98就是B。
事实上,真正出现二进制兼容性问题的时候,确实是报NoSuchMethodError或者NoSuchFieldError或者NoClassDefFoundError。Java api对NoSuchMethodError的解释(其他的解释几乎相同):
Thrown if an application tries to call a specified method of a class (either static or instance), and that class no longer has a definition of that method.
Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.
 
关键词是“incompatibly changed ”。
 
事实证明,当传统意义上的二进制不兼容性(既上面举的98的例子,或者说incompatibly changed)问题发生的时候,java会报NoSuchMethodError,NoSuchFieldError或者NoClassDefFoundError,这三个类都是LinkageError的子类,所以,就好像java api对LinkageError中的解释一样“Subclasses of LinkageError indicate that……”这个解释并没有说LinkageError本身应该是在什么情况下被抛出。倒不是java api顾左右而言他,而是抛出LinkageError的情况实在是很难叙述,《深入java虚拟机》第二版用近乎一章(比较大的一章,和其它章相比)来解释这个问题。归根结底,原因是ClassLoader没有完全按照设计的那样设置:任何一个ClassLoader的实例都应该设置一个恰当的ClassLoader实例为父类加载器,并且在真正defineClass前,都应该先将这个任务委托给其父类加载器。何为恰当的ClassLoader实例?一般来说,就应该是 this.getClass().getClassLoader()(也就是ClassName.class.getClassLoader(),这两个值是同一个值)的返回值),或者是一个设计者认为合理的值。这个值应该保证“相同全限定名的类(可以认为是同一个类,仅仅是可以)不会出现在同一个类的代码中。”举例来说,在一个类的一段代码中(可以是一个方法,或者是一个static块),如果有classLoaderA加载的 test.Test类,也有classLoaderB加载的test.Test,那么,把前者的引用指向后者的实例的时候,就会报LinkageError。
posted @   深夜两点  阅读(4637)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示