4大类加载器java_Java 不同类加载器如何使用被其他类加载器加载过的类?

就以典型的tomcat为例说明:

class A 位于xxa.jar中

class B 和 Class C 位于 xxbc.jar中

不论A先还是B先,肯定都是存在引用导致了classloader去加载了这个类,你现在是b中调用A的一个方法,以下是几种情况

class A 和 class B 是由各自的类加载器加载的,已知A先加载,B后加载。class C 与 B 在同一jar内,同一个类加载器加载。当我在B中调用A的一个方法,参数是C的新实例,就报ClassNotFoundException C

1、A被commonClassloader加载,b/c被webappClassloader加载,很显然,会抛出classNotFoundException,具体原因就是当前类中的数据只能由加载该类的类加载器加载。

2、A被webappClassloader加载,b/c被commonClassloader加载,b调用A的一个方法,参数是C的实例,这时爆出A not found,除非使用上下文加载器实例化A.

想在你的评论下放图的,放不了。就发这里了

4e384ee26b71ac5faed4720075357318.png

该图是我用Springboot的一个starter放置于tomcat/lib目录下(8.5.35版本),然后用Spring的component-scan扫描,通过@Configuration注册,随后通过我自定义的BeanFactoryPostProcessor修改bean信息,这个可以模拟A和B/C jar包的问题吧。

@Configuration

@ConditionalOnClass(name = {"org.springframework.beans.factory.config.BeanFactoryPostProcessor"})

public class MonitorAutoConfigure {

@Bean

public static BeanFactoryPostProcessor my() {

String lowerCase = MonitorAutoConfigure.class.getClassLoader().toString().toLowerCase();

System.out.println(lowerCase + "\tchen");

return new MyBeanFactoryPostProcessor(lowerCase.contains("webappclassloader") && !lowerCase.startsWith("org.springframework.boot"));

}

}

@临风 代码就只能放这么点了,涉及隐私,不好意思.

@临风 不好意思,没找到你的邮箱

先由webapp加载器将webinf/lib下的Class加载好,并实例化,然后传给由父加载器(common)加载的类的实例方法

这句话其实本身就是错误的,因为还没有等到你传递的过程,类加载的过程就已经失败了,具体原因就不说了,在添张图吧,具体的原因深入了解java虚拟机已经描述了。

环境:tomcat8.5.35(非插件) 启动Spring 5.0.7.RELEASE

604dce397ee7626261061750807c3bb2.png

报错图

94f71807761d7f108c6b76cd2d50ec69.png

实际代码

b35e4cfc32e3df357af3946b29610f9a.png

asm字节码

{

mv = cw.visitMethod(ACC_PUBLIC, "googo", "(Lorg/springframework/boot/ApplicationArguments;)Ljava/lang/Object;", null, null);

mv.visitCode();

Label l0 = new Label();

mv.visitLabel(l0);

mv.visitLineNumber(42, l0);

mv.visitInsn(ICONST_1);

mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);

mv.visitInsn(ARETURN);

Label l1 = new Label();

mv.visitLabel(l1);

mv.visitLocalVariable("this", "Lboot/raycloud/project/monitor/common/MonitorAutoConfigure;", null, l0, l1, 0);

mv.visitLocalVariable("applicationArguments", "Lorg/springframework/boot/ApplicationArguments;", null, l0, l1, 1);

mv.visitMaxs(1, 2);

mv.visitEnd();

}

@代码宇宙 喷人就拿点真才实学。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值