能不能自定义类java.lang.Math 测试
1 . 运行直接运行Math类代码
错误: 在类 java.lang.Math 中找不到 main 方法, 请将 main 方法定义为:
public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application
原因分析:
由于类加载采用委托机制,加载一个类的时候,会先通过其父加载器去查找是否有这个类,
明显,java本身自带了 java.lang.Math 这个类,并加载进来,所以肯定找不到 自定义类中的main方法,因此报错。
2 . 运行 ClassLoaderTest
报错:
/java/lang/Math.class
sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@5e2de80c
java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.MyClassLoader.loadClass(MyClassLoader.java:28)
at com.ClassLoaderTest.main(ClassLoaderTest.java:7)
Exception in thread "main" java.lang.ClassNotFoundException
at com.MyClassLoader.loadClass(MyClassLoader.java:31)
at com.ClassLoaderTest.main(ClassLoaderTest.java:7)
由堆栈异常信息可知道,当应用程序类加载器类(AppClassLoader)尝试加载MyMath类时, ClassLoader.java的479行抛出了SecurityException
直接查看抽象类java.lang.ClassLoader的preDefineClass方法代码
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;
}
由代码可知,直接运行代类全面以 java. 开头的时候,将会抛出SecurityException异常。 验证,执行 MyMath.java
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
验证成功。
3 . 为了避免双亲委托机制,如果我们自定义的类加载器放在一个特殊的目录,那么系统的加载器就无法加载,也就是最终还是由我们自己的加载器加载。 这样会不会成功呢?