Recently learned the following Java class loading related knowledge. And then see that there's an interview on the Internet
Can you write a class called Java.lang.System?
Answers available online: usually not, but alternative approaches can be taken to meet this requirement. The so-called alternative method refers to writing a class loader to load Java.lang.System to achieve the goal.
First of all, to show my point. The above answer is completely misleading and is an incorrect answer. I wonder how the online search results are completely incorrect, and it's almost always the wrong answer. Perhaps a lot of unknown truth friends are so misled, so I still hope that the content of the online first to be skeptical as well. Here's a detailed explanation of why.
First, a detailed explanation of the online error answer
"In order not to let us write the system class, class loading uses a delegation mechanism, which will ensure that dads first, dads can find the class, the son will not have the opportunity to load." The system class is loaded by the bootstrap loader, and even if you rewrite it, you always use the system provided by the Java systems, and the system class you write does not have a chance to get loaded at all.
However, we can define a class loader ourselves to do this, and in order to avoid the parental delegation mechanism, the classloader must be special. Because the system comes with three ClassLoader that load classes in a particular directory, if our own classloader is placed in a special directory, then the system loader will not load, that is, ultimately, our own loader load. ”
Then, describe some of the concepts mentioned in the explanation above
Class loaders can be divided into two categories: First, the Startup class loader (Bootstrap ClassLoader), which is implemented by C + +, is part of the JVM, and the other class loader, which is implemented in Java, is independent of the JVM, All inherit from the abstract class Java.lang.ClassLoader. The JDK comes with three kinds of loaders, namely the boot ClassLoader (Bootstrap ClassLoader), The Extension class loader (Extension ClassLoader), and the application ClassLoader (application ClassLoader). The latter two types of loaders are inherited from the abstract class Java.lang.ClassLoader. about the respective functions of these three loaders do not elaborate here, interested can be understood under their own.
The class loader is hierarchical
Typically: Custom ClassLoader >> application classloader >> Extension class loader >> start class loader
The above hierarchy is called the parental delegation model (parents delegation models). In addition to the topmost startup class loader, the rest of the ClassLoader has a corresponding parent classloader.
Let's just say the parent delegation mechanism: If a class loader receives a request for a class load, it first does not attempt to load the class itself, but instead delegates the request to the parent class loader, which is added to each level of the ClassLoader, so all the load requests finally reach the top-level startup class loader, The subclass loader will attempt to load itself only if the parent loader feedback that it cannot complete the load request (meaning that its search scope does not find the desired class).
Then go back to see the explanation, I believe the previous part of the people should be very understanding, there is no big problem. The last if part of "If our own classloader is placed in a special directory, then the system loader will not load, that is, ultimately, our own loader load." "I don't understand so, the logic is completely out of the way. I think it might have meant to put its own Java.lang.System class in a special directory, and then the system's own loader could not load, and ultimately it would have been loaded by our own loader (because our own loader knew the special directory it was in). There seems to be no logical problem with this argument, so let's experiment with it.
Code Validation
The test class structure and contents are as follows:
public class Myclassloader extends classloader{public Myclassloader () {Super (null); } @Override Public class<?> loadclass (String name) throws ClassNotFoundException {try{ String className = null; if (Name.startswith ("Java.lang")) {className = "/" + name.replace ('. ', '/') + ". Class"; }else{className = name.substring (Name.lastindexof ('. ') + 1) + ". Class"; } System.out.println (ClassName); InputStream is = GetClass (). getResourceAsStream (ClassName); System.out.println (IS); if (is = = null) return Super.loadclass (name); Byte[] B = new byte[is.available ()]; Is.read (b); Return DefineClass (name, b, 0, b.length); }catch (Exception e) {e.printstacktrace (); throw new ClassNotFoundException (); } }}
public class Classloadertest {public static void Main (string[] args) throws ClassNotFoundException, Instantiationexception, illegalaccessexception { ClassLoader myloader = new Myclassloader (); Object obj = Myloader.loadclass ("Java.lang.Math"). newinstance (); System.out.println (obj); } }
Public final class Math {public static void Main (string[] args) { System.out.println ("Hello World");} }
public class MyMath {public static void Main (string[] args) { System.out.println ("Hello World");} }
The above test code does not use the custom Java.lang.System class, because the test code uses the JDK's own system class for output printing, conflicts, so instead of using the custom Java.lang.Math class. If the custom math class can load, the custom system class can also be loaded.
Let's run the math class directly, with the output as follows:
Java.lang.NoSuchMethodError:main
Exception in thread "main"
Tip The Math class has no Main method. First of all, we need to understand a concept, when the first active use of the class, the class must be loaded, this part of the work is done by the ClassLoader. Based on the parental delegation principle, the math class first tries to load by starting the ClassLoader, and it is clear that It finds the Java.lang.Math class in Rt.jar and loads it into memory (does not load our custom math Class), and then executes the main method, discovering that the method does not exist, so the report method does not have an error. That is, the JVM does not load our custom math class by default.
Then run the MyMath class directly, the output is as follows:
java.lang.SecurityException:Prohibited Package Name:java.lang
At Java.lang.ClassLoader.preDefineClass (classloader.java:479)
At Java.lang.ClassLoader.defineClassCond (classloader.java:625)
At Java.lang.ClassLoader.defineClass (classloader.java:615)
At Java.security.SecureClassLoader.defineClass (secureclassloader.java:141)
At Java.net.URLClassLoader.defineClass (urlclassloader.java:283)
At java.net.urlclassloader.access$000 (urlclassloader.java:58)
At Java.net.urlclassloader$1.run (urlclassloader.java:197)
At java.security.AccessController.doPrivileged (Native Method)
At Java.net.URLClassLoader.findClass (urlclassloader.java:190)
At Java.lang.ClassLoader.loadClass (classloader.java:306)
At Sun.misc.launcher$appclassloader.loadclass (launcher.java:301)
At Java.lang.ClassLoader.loadClass (classloader.java:247)
Exception in thread "main"
Note the contents of the Red section. By the stack exception information, when the Application class loader class (Appclassloader) tries to load the MyMath class, the 479 rows of Classloader.java throw out the SecurityException
Prohibit the use of package name: Java.lang.
Direct view of the abstract class Java.lang.ClassLoader Predefineclass method code, excerpt as follows:
Private Protectiondomain Predefineclass (String name, protectiondomain protectiondomain) {if (!checkname ( Name) throw new Noclassdeffounderror ("Illegalname:" + name); if ((name! = null) && name.startswith ("java.")) { 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; }
You can see if the class full name is loaded with "java." At the beginning, SecurityException will be thrown, which is why the direct execution of the MyMath class will appear SecurityException.
In this way, our custom ClassLoader must inherit from ClassLoader, whose loadclass () method calls the parent class's DefineClass () method, and finally to the Predefineclass () method, So our custom class loader is also not loaded with "java." The beginning of the Java class. We continue to run the next Classloadertest class, with the output as follows:
/java/lang/math.class
[Email Protected]ca
java.lang.SecurityException:Prohibited Package Name:java.lang
At Java.lang.ClassLoader.preDefineClass (classloader.java:479)
At Java.lang.ClassLoader.defineClassCond (classloader.java:625)
At Java.lang.ClassLoader.defineClass (classloader.java:615)
At Java.lang.ClassLoader.defineClass (classloader.java:465)
At Com.tq.MyClassLoader.loadClass (myclassloader.java:28)
At Com.tq.ClassLoaderTest.main (Classloadertest.java:8)
Exception in thread "main" java.lang.ClassNotFoundException
At Com.tq.MyClassLoader.loadClass (myclassloader.java:31)
At Com.tq.ClassLoaderTest.main (Classloadertest.java:8)
The Red section clearly indicates that the SecurityException is also thrown in the Predefineclass method.
Code examples and source analysis can be seen, for the custom class loader, forced to use the DefineClass () method to load a "java." The class at the beginning will also throw an exception.
Summarize
Cannot write by itself "java." Begins with a class that either cannot be loaded into memory, or even if you forcibly load it with a custom class loader, you receive a SecurityException.
Code word is not easy, source from http://blog.csdn.net/tang9140.
Those who crawl online content, on their own website, please consciously. Baidu Search Why do you keep the original page row behind it, please reflect, do not just want to make money.
Java can write itself a class called java.lang.system/string correct answer