java.lang.String_自己写的java.lang.String可以让jvm加载到吗?

git

前言

老问题了,到网上也一搜一堆答案,比如,随便来一篇

df7dd19e2a0f0c7c706756b8ad0b3354.png

乍一看好像没什么问题,但是在掌握自定义类加载器之后,知道如何打破双亲委派之后再回头来看这段话发现有两个问题:

1:凭什么你认为我现在是ApplicationClassLoader? 毕竟很多框架都会自定义类加载器的

2: 凭什么你认为我一定要走双亲委派?

怀疑当然要有个证据,那么我们就写一段程序:

1:打破双亲委派

2:写一个java.lang.String类

代码见git

《2020最新Java基础精讲视频教程和学习路线!》

一些重要的地方截取出来看看package java.lang;

public class String {

private Integer a;

public Integer getA() {

return a;

}

public void setA(Integer a) {

this.a = a;

}

}package org.wayne;

import org.wayne.util.ClassLoaderUtil;

import java.lang.reflect.Method;

public class RegisterDriverUtil {

public static void register(String name){

Class pluginClass = ClassLoaderUtil.getPluginClass(RegisterDriverUtil.class);

try {

Method method = pluginClass.getDeclaredMethod("register", String.class);

method.setAccessible(true);

method.invoke(pluginClass.newInstance(),name);

} catch (Exception e) {

throw new RuntimeException(e);

}

}

}package org.wayne;

public class RegisterDriverUtil {

public void register(String name) throws ClassNotFoundException {

Class.forName(name);

}

}public static void test8(){

EnvironmentUtil.setEnv(EnvEnum.A);

RegisterDriverUtil.register("java.lang.String");

EnvironmentUtil.clearEnv();

}

打包,在wsl下运行,结果如下

8081daa3a129e8b3250a38ec5342964d.png

推测:

1:代码里是用自定义类加载器直接加载的java.lang.String类,并没有走双亲委派

2:由报错来看,是java.lang.ClassLoader阻止了加载

原因

无论何种自定义类加载器,最后都是调用的defineClass方法加载byte[],注释如下

ff0ba0ae848e3de38b3f89f4c57e6da9.pngprotected final Class> defineClass(String name, byte[] b, int off, int len,

ProtectionDomain protectionDomain)

throws ClassFormatError

{

protectionDomain = preDefineClass(name, protectionDomain);

String source = defineClassSourceLocation(protectionDomain);

Class> c = defineClass1(name, b, off, len, protectionDomain, source);

postDefineClass(c, protectionDomain);

return c;

}

/* Determine protection domain, and check that:

- not define java.* class,

- signer of this class matches signers for the rest of the classes in

package.

*/

private ProtectionDomain preDefineClass(String name,

ProtectionDomain pd)

{

if (!checkName(name))

throw new NoClassDefFoundError("IllegalName: " + name);

// Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias

// relies on the fact that spoofing is impossible if a class has a name

// of the form "java.*"

if ((name != null) && name.startsWith("java.")) {

throw new SecurityException

("Prohibited package name: " +

name.substring(0, name.lastIndexOf('.')));

}

if (pd == null) {

pd = defaultDomain;

}

if (name != null) checkCerts(name, pd.getCodeSource());

return pd;

}

结论

1:无论何种自定义类加载器,最终都会调用ClassLoader.defineClass

2:ClassLoader.defineClass中会检查类名,类名以java.开头的,不予加载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值