【java】LinkageError之loader (instance of xxx) previously initiated loading for a different type

本文主要是介绍【java】LinkageError之loader (instance of xxx) previously initiated loading for a different type,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LinkageError包括其子类,是Java中比较不应该出现的Error。出现这些问题,大概有几个问题:ClassLoader没有严格遵守Java中默认的双亲委派模式;全限定名相同的两个类在不同的CL中有重复;程序运行时使用的类的版本与开发时候不一样(类有变化,比如改了方法的可见性等)。

而LinkageError本身则更少见。当遇到LinkageError loader (instance of xxx) previously initiated loading for a different type with name "lib/MyData"时,可以肯定系统中有ClassLoader违背了Parent Delegate的规则。

问题的根源就是,当一个类已经被解析过之后,它用到的其它类也就已经确定并被解析好了。这时候,如果另一个CL也加载了同一个类(类名相同),并尝试将这个类的实例给前面的引用赋值,因为实际上两个类是由不同的类加载器加载的,既在JVM看来是不同的类,所以就会出现这个错误。

下面是一个简单的例子。没有实际意义,只为了展示问题。

系统中的几个角色类:

IFac - 接口,提供一个getMyData方法。

MyData - 数据类,没有实际意义,但是在系统中,这个类的加载则是引发问题的关键

IFacImpl - IFac接口的实现。

系统中还有一个不可或缺的角色——那个不遵守规则的ClassLoader。我们需要自己写一个ClassLoader来违法Parent Delegate的规则。

复制代码
 1 package webcl;
2
3 import java.net.URL;
4 import java.net.URLClassLoader;
5 import java.net.URLStreamHandlerFactory;
6
7 public class WebAppCL extends URLClassLoader {
8
9 public WebAppCL(URL[] urls, ClassLoader parent,
10 URLStreamHandlerFactory factory) {
11 super(urls, parent, factory);
12 }
13
14 public WebAppCL(URL[] urls, ClassLoader parent) {
15 super(urls, parent);
16 }
17
18 public WebAppCL(URL[] urls) {
19 super(urls);
20 }
21
22 @Override
23 protected synchronized Class<?> loadClass(String name, boolean resolve)
24 throws ClassNotFoundException {
25 try {
26 return findClass(name);
27 } catch (ClassNotFoundException ex) {
28 return super.loadClass(name, resolve);
29 }
30 }
31
32 }
复制代码

  

这个ClassLoader唯一的作用就是违反PD的规则。

然后是App程序:

复制代码
 1 package test;
2
3 import java.net.URL;
4
5 import lib.IFac;
6 import lib.MyData;
7 import webcl.WebAppCL;
8 public class App2 { // 应用程序的classpath上有IFac类和MyData类。
9 public static void main(String[] args) throws Exception {
10 MyData resolved = new MyData();
11 WebAppCL cl = new WebAppCL(new URL[] {
12 new URL("file:\\C:\\Users\\zangmeng\\Desktop\\data.jar"), // 包含MyData类
13 new URL("file:\\C:\\Users\\zangmeng\\Desktop\\faclib.jar") }); // 包含FacImpl类,不包含IFac类。
14 IFac fac = (IFac) cl.loadClass("faclib.FacImpl").newInstance();
15 MyData data = fac.getData();
16 }
17 }
复制代码

  

程序在运行时,类加载情况如下所示:

程序很简单,四行代码而已。

第一行是创建一个MyData的实例。目的是让MyData类被加载和解析。

第二行是创建一个WebAppCL,这个不听话的CL会优先加载自己classpath下的类,如果失败了再去问parent cl要。现在这个CL可以加载MyData类和FacImpl类。

第三行,首先是IFac fac这段。JVM需要使用当前类加载器,也就是AppClassLoader,加载并解析IFac类,解析的过程中,同时链接到AppCL加载的MyData类。等号的另一边,通过WebCl加载并创建一个FacImpl的实例。这个时候,因为WebAppCL会首先从自己的CP里加载类,所以在解析FacImpl的时候,加载MyData的请求并没有被委派到AppCL,而是自己自己消化了,这时候JVM里面就有两个MyData类了。但是程序到这里并没有错误,因为WebAppCL里面并没有IFac接口,这个接口还是AppCL的,但是这时候隐患已经埋下了——

FacImpl类在解析的时候,需要MyData类,而这个MyData类是被WebCL加载的。

IFac则不同,它的MyData类是被AppCL加载的。

FacImpl实现了IFac接口,按说getMyData方法应该返回相同的类型。而在runti的时候,这两个MyData却是不同的类型,因为它们是被不同的CL加载的。

第四行是引起错误的地方。等号左边的MyData实际上是第一行中那个被AppCL加载的类的一个引用。等号右边返回的MyData实例是被WebCL加载的MyData的实例。两个不同的类型,赋值自然会引发错误。

这篇关于【java】LinkageError之loader (instance of xxx) previously initiated loading for a different type的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/477824

相关文章

Java如何根据word模板导出数据

《Java如何根据word模板导出数据》这篇文章主要为大家详细介绍了Java如何实现根据word模板导出数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... pom.XML文件导入依赖 <dependency> <groupId>cn.afterturn</groupId>

Java应用如何防止恶意文件上传

《Java应用如何防止恶意文件上传》恶意文件上传可能导致服务器被入侵,数据泄露甚至服务瘫痪,因此我们必须采取全面且有效的防范措施来保护Java应用的安全,下面我们就来看看具体的实现方法吧... 目录恶意文件上传的潜在风险常见的恶意文件上传手段防范恶意文件上传的关键策略严格验证文件类型检查文件内容控制文件存储

浅析Java如何保护敏感数据

《浅析Java如何保护敏感数据》在当今数字化时代,数据安全成为了软件开发中至关重要的课题,本文将深入探讨Java安全领域,聚焦于敏感数据保护的策略与实践,感兴趣的小伙伴可以了解下... 目录一、Java 安全的重要性二、敏感数据加密技术(一)对称加密(二)非对称加密三、敏感数据的访问控制(一)基于角色的访问

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,

使用Java将实体类转换为JSON并输出到控制台的完整过程

《使用Java将实体类转换为JSON并输出到控制台的完整过程》在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用JSON格式,用Java将实体类转换为J... 在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用j

Java实现视频格式转换的完整指南

《Java实现视频格式转换的完整指南》在Java中实现视频格式的转换,通常需要借助第三方工具或库,因为视频的编解码操作复杂且性能需求较高,以下是实现视频格式转换的常用方法和步骤,需要的朋友可以参考下... 目录核心思路方法一:通过调用 FFmpeg 命令步骤示例代码说明优点方法二:使用 Jaffree(FF

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

Java如何用乘号来重复字符串的功能

《Java如何用乘号来重复字符串的功能》:本文主要介绍Java使用乘号来重复字符串的功能,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java乘号来重复字符串的功能1、利用循环2、使用StringBuilder3、采用 Java 11 引入的String.rep

SpringBoot中HTTP连接池的配置与优化

《SpringBoot中HTTP连接池的配置与优化》这篇文章主要为大家详细介绍了SpringBoot中HTTP连接池的配置与优化的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、HTTP连接池的核心价值二、Spring Boot集成方案方案1:Apache HttpCl

Spring Boot项目打包和运行的操作方法

《SpringBoot项目打包和运行的操作方法》SpringBoot应用内嵌了Web服务器,所以基于SpringBoot开发的web应用也可以独立运行,无须部署到其他Web服务器中,下面以打包dem... 目录一、打包为JAR包并运行1.打包为可执行的 JAR 包2.运行 JAR 包二、打包为WAR包并运行