java类的加载
1 jvm默認有3類class loader
bootstrap class loader,啟動類加載器,負責(zé)加載${java_home}/jre/lib目錄下的庫,比如java基礎(chǔ)類庫包rt.jar
extension class loader,擴展類加載器,負責(zé)加載${java_home}/jre/lib/ext目錄下的庫,即第三房擴展庫。
application class loader,應(yīng)用程序類加載器,負責(zé)加載classpath指定的用戶的類庫。
2 加載什么
class loader加載的是庫中的類,而不是整個庫加載進jvm。加載進整個庫是完全沒有必要的,是非常浪費內(nèi)存的,這個和動態(tài)鏈接庫不同,動態(tài)鏈接庫是整個都要加載進內(nèi)存中。
3 加載一個類的過程
bootstrap class loader是extention class loader的父類,extension class loader是application class loader的父類。
如果一個類加載器收到了一個類加載的請求,它不會自己去加載,而是讓父加載器先加載,只有當父加載器加載不了時,它才去加載。
這樣設(shè)計的好處是明顯的,保證了Object類在程序中是唯一的,無論是誰加載,最終都是bootstrap class loader從rt.jar中加載的Object類。否則java程序就回混亂了。
4 類加載的時機
當要用到某個類的時候才會去加載這個類,否則是不會加載這個類的。具體來說,就是出現(xiàn)了new關(guān)鍵字,需要創(chuàng)建這個類的對象的時候,會去加載這個類。加載這個類的時候,class loader是去相應(yīng)的目錄下根據(jù)包名找到這個類,然后加載進來。
所以,類加載三點是很重要的東西:第一,new關(guān)鍵字,第二,import時候的包名,第三,類加載器的搜索目錄,它會去這個目錄下搜索第二個信息指定的類。
驗證手段如下:
The rules for loading classes are spelled out in detail in the JVM specification. The basic principle is that classes are only loaded when needed (or at least appear to be loaded this way -- the JVM has some flexibility in the actual loading, but must maintain a fixed sequence of class initialization). Each class that gets loaded may have other classes that it depends on, so the loading process is recursive. The classes in Listing 2 show how this recursive loading works. The Demo class includes a simple main method that creates an instance of Greeter and calls the greet method. The Greeter constructor creates an instance of Message, which it then uses in the greet method call.
source code:
public class Demo { ????public static void main(String[] args) { ????????System.out.println("**beginning execution**"); ????????Greeter greeter = new Greeter(); ????????System.out.println("**created Greeter**"); ????????greeter.greet(); ????} } public class Greeter { ????private static Message s_message = new Message("Hello, World!"); ????? ????public void greet() { ????????s_message.print(System.out); ????} } public class Message { ????private String m_text; ????? ????public Message(String text) { ????????m_text = text; ????} ????? ????public void print(java.io.PrintStream ps) { ????????ps.println(m_text); ????} } Setting the parameter -verbose:class on the java command line prints a trace of the class loading process. Listing 3 shows partial output from running the Listing 2 program with this parameter: [Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Opened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar] [Opened /usr/java/j2sdk1.4.1/jre/lib/jsse.jar] [Opened /usr/java/j2sdk1.4.1/jre/lib/jce.jar] [Opened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar] [Loaded java.lang.Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded java.io.Serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded java.lang.Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded java.lang.CharSequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded java.lang.String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] ... [Loaded java.security.Principal from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded java.security.cert.Certificate ??from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded Demo] **beginning execution** [Loaded Greeter] [Loaded Message] **created Greeter** Hello, World! [Loaded java.util.HashMap$KeySet ??from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] [Loaded java.util.HashMap$KeyIterator ??from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]This is only a partial listing of the most important parts -- the full trace consists of 294 lines, most of which I deleted for this listing. The initial set of class loads (279, in this case) are all triggered by the attempt to load the Demo class. These are the core classes that are used by every Java program, no matter how small. Even eliminating all the code from the Demo main method doesn't affect this initial sequence of loads. The number and names of classes involved will differ from one version of the class libraries to another, though.
The portion of the listing after the Demo class is loaded is more interesting. The sequence here shows that the Greeter class is only loaded when an instance of the class is about to be created. However, the Greeter class uses a static instance of the Message class, so before an instance of the former can be created, the latter class also needs to be loaded.
A lot happens inside the JVM when a class is loaded and initialized, including decoding the binary class format, checking compatibility with other classes, verifying the sequence of bytecode operations, and finally constructing a java.lang.Class instance to represent the new class. This Class object becomes the basis for all instances of the new class created by the JVM. It's also the identifier for the loaded class itself -- you can have multiple copies of the same binary class loaded in a JVM, each with its own Class instance. Even though these copies all share the same class name, they will be separate classes to the JVM.
?參考資料:
1. https://www.ibm.com/developerworks/library/j-dyn0429/
轉(zhuǎn)載于:https://www.cnblogs.com/hustdc/p/6431686.html
超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生總結(jié)
- 上一篇: Watson使用指南(三)
- 下一篇: 50行代码搞定无限滑动幻灯片