使用idea创建了一个新的工程,然后建了一个名为“java”的文件夹,当启动里面的主函数时,出现如下异常:
根据异常信息,定位到java.lang.ClassLoader.preDefineClass进行排查,发现以下代码片断:
-
/* 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 protectionDomain)
-
{
-
if (!
checkName(name))
-
throw
new
NoClassDefFoundError(
"IllegalName: " + name);
-
if ((name !=
null) && [color=red]name.
startsWith(
"java.")[/color]) {
-
throw
new
SecurityException(
"Prohibited package name: " +
-
name.
substring(
0, name.
lastIndexOf(
'.')));
-
}
-
if (protectionDomain ==
null) {
-
protectionDomain =
getDefaultDomain();
-
}
-
-
if (name !=
null)
-
checkCerts(name, protectionDomain.
getCodeSource());
-
-
return protectionDomain;
-
}
-
-
......
-
-
// true if the name is null or has the potential to be a valid binary name
-
private
boolean
checkName(
String name) {
-
if ((name ==
null) || (name.
length() ==
0))
-
return
true;
-
if ((name.
indexOf(
'/') != -
1)
-
|| (!
VM.
allowArraySyntax() && (name.
charAt(
0) ==
'[')))
-
return
false;
-
return
true;
-
}
可以看出preDefineClass方法首先对类名进行了检查,发现以java作为一级包名,则抛出安全异常:禁止使用的包名!
这条安全异常是由Java类加载的“双亲委派模型”(详见这里)所导致的。在双亲委派模型中,由父加载类加载的类,下层加载器是不能加载的。本例中最高层加载器BootstrapClassLoader加载了classpath路径下所定义的java.*包内的类,而java.research包就不能由BootstrapClassLoader的下层加载器AppClassLoader加载了。这也是java安全机制中对于恶意代码所采取的防护措施。