zoukankan      html  css  js  c++  java
  • jvm知识汇总

    1. Jre的选用

    如果安装JDK1.3那么安装程序一定会同时安装两套JRE。

        一套位于 jdk\jre目录

        一套位于program files\JavaSoft目录

        JDK里面的工具几乎全是用java所写的,所以JDK本身就是Java应用程序,因此要用JDK附的工具来开发Java程序,也必须要自行附一套JRE才行。这就是JDK安装目录\jre下需要一套JRE的原因。

        位于program files\下的那套JRE就是拿来执行我们自己写的java应用程序。

        不过,两套中任何一套JRE 都可以拿来执行我们所撰写的Java 应用程序,

    可是JDK 内附的开发工具在预设使用包装器(.exe) 来启动的情形下,都会自己去选用\jre 底下那套JRE。

    2.   到底是执行哪一个java.exe

    java xxx

    当一台机器上有多个jvm可选择的时候,jvm的选择步骤:

        1)当前目录有没有jre目录(不准确),

        2)父目录下的jre子目录

        3)注册表HEKY_LOCAL_MACHINE\SoftWare\Java\Java Runtime Environment\

    所以当运行的是jdk\bin\java.exe的时候,用的jre是bin的父目录jdk下面的jre\

        在system32目录 底下找不到JRE 目录,在c:\windows目录 也找不到JRE 目录的情况下,根据下一个逻辑,就是去查询注册表

        java.exe在system32目录、program files\JavaSoft目录、jdk\jre目录都有一般先找的是system32下的。注册表注册的一般是program files\JavaSoft目录

       

        运行java.exe找到了jre后有一个验证程序,verify.dll验证jre和java.exe的版本是否一致,如果不一致则会发生错误

       

        一般把常用的工具档放到JDK目录\jre\lib\ext下,把有关安全机制的配置文件放到JDK目录\jre\lib\security下

    3.   类加载器

        每个类对java机来说,都是一个独立的动态联结函数库,只不过扩展名不是.dll或.so 而是.class

        程序运行时需要的核心类库位于 jre\lib\rt.jar中

        类加载器的作用就是把类从表态的硬盘 .class文件,复制一份到内存中,并做一此 始化工作

        java.exe就是利用几个原则找到JRE后,把.class直接转交给JRE运行后便功成身退

    3.1.   classloader的两种载入方式:

    1)pre-loading预先载入,载入基础类

    2)load-on-demand按需求载入

        只有实例化一个类时,该类才会被classloader载入,仅仅申明并不会载入

        基础类库是预先加载的(pre-loading)

        用户所写的一般类是按需加载的(load-on-demand)按需加载,依需求加载的优点是节省内存,但是仍有其缺点。举例来说,当程序第一次用到该类别的时候,系统就必须花一些额外的时间来加载该类别。

    3.2.   使JAVA程序更有动态性的方法有两种

    1)implicit隐式,即利用实例化才载入的特性来动态载入class

    2)explicit显式方式,又分两种方式:

    _      java.lang.Class的forName()方法

    _      java.lang.ClassLoader的loadClass()方法

    第一种方法: Class.forName() 加载类

    一个是只有一个参数的:

        public static Class forName(String className)

    一个是需要三个参数的:

        public static Class forName(String name, boolean initialize,ClassLoader loader)

    这两个方法,最后都是连接到原生方法forName0()

    其宣告如下:

    private static native Class forName0(String name,boolean initialize, ClassLoader loader) throws ClassNotFoundException;

    只有一个参数的forName()方法,最后调用的是:

        forName0(className, true,ClassLoader.getCallerClassLoader());

        ClassLoader.getCallerClassLoader() 来取得加载呼叫他的类别所使用的类别加载器,是一个private 的方法,所以我们无法自行叫用。

    具有三个参数的forName()方法,最后调用的是:

        forName0(name, initialize, loader);

    不管您使用的是new 来产生某类别的实例、或是使用只有一个参数的forName()方法,内部都隐含了”加载类别+呼叫静态初始化区块”的动作。

    static块在什么时候执行?

        1)当调用forName(String)载入class时执行,如果调用ClassLoader.loadClass并不会执行.forName(String,false,ClassLoader)时也不会执行.

        2)如果载入Class时没有执行static块则在第一次实例化时执行.比如new ,Class.newInstance()操作

        3)static块仅执行一次

    第二种:直接使用ClassLoader 类别的loadClass() 方法来加载类

    此方式只会把类加载至内存,并不会调用该类别的静态初始化区块,而必须等到第一次实例化该类别时,该类别的静态初始化区块才会被叫用。

    这种情形与使用Class 类别的forName()方法时,第二个参数传入false 几乎是相同的结果。

    Class类的实例.

    4.   Class类的实例.

    _      Class类无法手工实例化,当载入任意类的时候自动创建一个该类对应的Class的实例,

    _      某个类的所有实例内部都有一个栏位记录着该类对应的Class的实例的位置.,

    _      每个java类对应的Class实例可以当作是类在内存中的代理人.所以当要获得类的信息(如有哪些类变量,有哪些方法)时,都可以让类对应的Class的实例代劳。

           java的Reflection机制就大量的使用这种方法来实现

    _      每个java类都是由某个classLoader(ClassLoader的实例)来载入的,因此Class类别的实例中都会有栏位记录他的ClassLoader的实例,如果该栏位为null,则表示该类别是由bootstrap loader载入的(也称root laoder),bootstrap loader不是java所写成,所以没有实例.


    5.   Java启动过程

             当我们在命令行输入java xxx.class 的时候,java.exe 根据我们之前所提过的逻辑找到了JRE(Java Runtime Environment) ,

        接着找到位在JRE 之中的jvm.dll( 真正的Java 虚拟机),最后加载这个动态联结函式库,启动Java 虚拟机。

        虚拟机一启动,会先做一些初始化的动作,比方说抓取系统参数等。一旦初始化动作完成之后,就会产生第一个类别加载器,

        即所谓的Bootstrap Loader,Bootstrap Loader 是由C++ 所撰写而成(所以前面我们说,以Java的观点来看,逻辑上并不存在Bootstrap Loader 的类别实例,所以在Java 程序代码里试图印出其内容的时候,我们会看到的输出为null),这个Bootstrap Loader所做的初始工作中,

       

    除了也做一些基本的初始化动作之外

        最重要的就是加载定义在sun.misc 命名空间底下的Launcher.java 之中的ExtClassLoader,并设定其Parent 为null,代表其父加载器为Bootstrap Loader 。

        然后Bootstrap Loader ,再要求加载定义于sun.misc 命名空间底下的Launcher.java 之中的AppClassLoader,并设定其Parent 为之前产生的ExtClassLoader 实例。

        这里要请大家注意的是,Launcher$ExtClassLoader.class与Launcher$AppClassLoader.class 都是由Bootstrap Loader 所加载,所以Parent 和由哪个类别加载器加载没有关系,AppClassLoader 和ExtClassLoader 都是URLClassLoader 的子类别。


    6.   Classloader的加载路径

    AppClassLoader

        由于它是URLClassLoader 的子类别,所以它们也应该有URL 作为搜寻类别档的参考AppClassLoader 所参考的URL 是从系统参数java.class.path 取出的字符串所决定,

        而java.class.path 则是由我们在执行java.exe 时,

        利用 –cp 或-classpath 或CLASSPATH 环境变量所决定。

    搜寻路径:

        在预设情况下,AppClassLoader的搜寻路径为”.”( 目前所在目录),

        如果使用-classpath 选项(与-cp 等效),就可以改变AppClassLoader 的搜寻路径,

        如果没有指定-classpath 选项,就会搜寻环境变量CLASSPATH 。

        如果同时有CLASSPATH 的环境设定与-classpath 选项,则以-classpath 选项的内容为主,CLASSPATH 的环境设定与-classpath 选项两者的内容不会有加成的效果。

    ExtClassLoader:

        也有相同的情形,不过其搜寻路径是参考系统参数java.ext.dirs

    Bootstrap Loader:

       用sun.boot.class.path来搜寻类别的路径

    特别注意:

    _      是否加载子目录

        AppClassLoader 与Bootstrap Loader 不会递归式地搜寻这些位置下的其他路径或其他没有被指定的JAR 文件。

        ExtClassLoader,所参考的系统参数是java.ext.dirs,意思是说,他会搜寻底下的所有JAR 文件以及classes 目录。

    _      启动后是否可以改变

        AppClassLoader 与ExtClassLoader 在整个虚拟机之中只会存有一份,一旦建立了,其内部所参考的搜寻路径将不再改变,也就是说,即使我们在程序里利用System.setProperty() 来改变系统参数的内容,仍然无法更动AppClassLoader 与ExtClassLoader 的搜寻路径

    委拖模型:类加载器有加载类别的需求时,会先请示其Parent 使用其搜寻路径帮忙加载,如果Parent 找不到,那么才由自己依照自己的搜寻路径搜寻类别。


    7.   JVM 的调试特性

    详细输出

        可以用 -verbose 命令行选项打开 IBM JVM 的详细输出。当某些事件发生的时候(例如,类装入时),详细输出会在控制台上显示信息。要想得到额外的类装入信息,可以用详细类输出。

        可以用 -verbose:class 选项启动这个模式。

    解释详细输出
    详细输出列出已经打开的所有 JAR 文件,包括到这些 JAR 的完整路径。下面是一个示例:

    ...

    [Opened D:\jre\lib\core.jar in 10 ms]

    [Opened D:\jre\lib\graphics.jar in 10 ms]

    ...

  • 相关阅读:
    WIFI芯片,结构光和ToF
    Ubuntu + Python
    React-Native 报错处理
    GPS && AGPS
    Feed流
    Kafka基础知识总结
    Kafka海量日志收集架构之Watcher监控告警-watcher 基础语法与使用
    4-23学习心得
    4-22 学习心得
    4-21学习心得
  • 原文地址:https://www.cnblogs.com/danghuijian/p/4400880.html
Copyright © 2011-2022 走看看