zoukankan      html  css  js  c++  java
  • java类的加载

    1 jvm默认有3类class loader

    bootstrap class loader,启动类加载器,负责加载${java_home}/jre/lib目录下的库,比如java基础类库包rt.jar

    extension class loader,扩展类加载器,负责加载${java_home}/jre/lib/ext目录下的库,即第三房扩展库。

    application class loader,应用程序类加载器,负责加载classpath指定的用户的类库。

    2 加载什么

    class loader加载的是库中的类,而不是整个库加载进jvm。加载进整个库是完全没有必要的,是非常浪费内存的,这个和动态链接库不同,动态链接库是整个都要加载进内存中。

    3 加载一个类的过程

    bootstrap class loader是extention class loader的父类,extension class loader是application class loader的父类。

    如果一个类加载器收到了一个类加载的请求,它不会自己去加载,而是让父加载器先加载,只有当父加载器加载不了时,它才去加载。

    这样设计的好处是明显的,保证了Object类在程序中是唯一的,无论是谁加载,最终都是bootstrap class loader从rt.jar中加载的Object类。否则java程序就回混乱了。

    4 类加载的时机

    当要用到某个类的时候才会去加载这个类,否则是不会加载这个类的。具体来说,就是出现了new关键字,需要创建这个类的对象的时候,会去加载这个类。加载这个类的时候,class loader是去相应的目录下根据包名找到这个类,然后加载进来。

    所以,类加载三点是很重要的东西:第一,new关键字,第二,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/

  • 相关阅读:
    设计模式的征途—12.享元(Flyweight)模式
    设计模式的征途—11.外观(Facade)模式
    UML类图10分钟快速入门
    设计模式的征途—10.装饰(Decorator)模式
    设计模式的征途—9.组合(Composite)模式
    设计模式的征途—8.桥接(Bridge)模式
    我的2017OKR
    设计模式的征途—7.适配器(Adapter)模式
    《白夜行》读后感:白夜行走,暗中羁绊
    设计模式的征途—6.建造者(Builder)模式
  • 原文地址:https://www.cnblogs.com/hustdc/p/6431686.html
Copyright © 2011-2022 走看看