1、 Java总体(java编程语言、java API、java文件格式和虚拟机) 1
2、 java虚拟机结束生命周期 1
3、 类的加载、连接和初始化 2
4、 java对类的使用方式分为两种: 2
4、 类的加载 2
5、 加载.class文件的方式 2
6、 两种类加载器 3
7、 类的连接阶段:就是将已经读入内存的二进制数据合并到虚拟机的运行时环境中去 3
8、 类的验证的内容: 3
9、 类的准备和解析: 3
10、 类的初始化: 3
11、 类的初始化时机:类被主动调用时*(六种 上面) 3
12、 类加载器: 3
13、 类的验证: 3
14、 类的准备和解析 3
15、 类的初始化步骤: 3
16、 类的初始化的时机 4
17、 类的加载父类委托机制(更好的保证java平台安全??): 4
18、类加载器: 4
19、 类的命名空间: 4
20、 JVM内存管理机制 4
21、 java堆和栈的区别:内存划分为堆内存和栈内存 5
22、 java内存泄露和内存溢出 5
23、 JVM工作原理 5
1、Java总体(java编程语言、java API、java文件格式和虚拟机)
2、java虚拟机结束生命周期
A、执行System.exit()方法
B、程序正常执行结束
C、程序执行过程中遇到异常或错误而异常终止
D、由于操作系统出现错误而导致java虚拟机进程终止
3、类的加载、连接和初始化
A、加载:查找并加载类的进制数据
B、连接:
验证:确保被加载类的正确性
准备:为类的静态变量分配内存,并将其初始化为默认值
解析:把类中的符号引用转换为直接引用
C、初始化:为类的静态变量赋予正确的初始值
4、java对类的使用方式分为两种:
所有java虚拟机实现必须在每个类或接口被java程序“首次主动使用”时才初始化他们
A、主动使用(会导致类的初始化)
Ø 创建类的实例
Ø 访问某个类或接口的静态变量,或者对该静态变量赋值
Ø 调用类的静态方法
Ø 反射(如Class.forName("com.ss.Test"))
Ø 初始化一个类的子类
Ø Java虚拟机启动时被标明为启动的类
除以上六种情况,其它使用java类的方式都被看作是对类的被动使用,不会导致类的初始化
B、被动使用
4、类的加载
是指将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装方法和区内的数据结构
5、加载.class文件的方式
A、从本地系统中直接加载
B、通过网络下载.class文件
C、从ZIP,JAR等归档文件中加载.class文件
D、从专有数据库中提取.class文件
E、将java源文件动态编译为.class文件
6、两种类加载器
A、java虚拟机自带的加载器
Ø 根类加载器(Bootstrap)
Ø 扩展类加载器(Extension)
Ø 系统类加载器(System)
B、用户自定义的类加载器
Ø java.lang.ClassLoader的子类
Ø 用户可以定制类的加载方式
7、类的连接阶段:就是将已经读入内存的二进制数据合并到虚拟机的运行时环境中去
8、类的验证的内容:
A、类文件的结构检查:确保类文件遵从Java类文件的固定格式
B、语义检查:确保类本身符合JAVA语言的语法规定,比如验证final类型的类没有子类,以及final类型的方法有没有被覆盖
C、字节码的验证:确保字节码流(由操作码的单字节指令组成)可以被虚拟机安全的执行。
D、二进制兼容性的验证:确保相互引用的类之间协调一致。
9、类的准备和解析:
A、准备:JAVA虚拟机为类的静态变量分配内存,并设置默认値。
B、解析:JAVA虚拟机会把类的二进制数据中的符号引用替换为直接引用。
10、类的初始化:
A、静态变量初始化:静态变量的声明式初始化和静态变量在初始化块中初始化。
B、初始化步骤:
Ø 假如类没有被加载和连接,那先进行加载和连接
Ø 假如类存在直接的父类,并且这个父类没有被初始化,那先初始化直接的父类
Ø 假如类中存在初始化,那依次执行初始化语句
11、类的初始化时机:类被主动调用时*(六种 上面)
Ø 只有当程序访问的静态变量或静态方法确实在当前类或当前接口定义时,才可以认为是对类或接口的主动使用
Ø 调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化
12、类加载器:
A、JAVA虚拟机自带的加载器:根类加载器(Bootstrap)、扩展类加载器(Extension)、系统类加载器(System)
B、用户自定义的类加载器:java.lang.ClassLoader的子类、用户可以定制类的加载方式
类的加载时机:JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载时遇到.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError)。如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误。
13、类的验证:
类被加载后就进入了连接阶段,连接就是将已经读入内存的类的二进制数据合并到虚拟机的运行环境中去。
A、验证的内容:
Ø 类文件的结构检查:确保类文件遵从JAVA类文件的固定格式
Ø 语义检查:确保类本身符合JAVA语言的语法规定。比如验证final类型的类没有子类,以及final类型的方法没有被覆盖。
Ø 字节码验证:确保字节码流可以被java虚拟机安全的执行。(字节码:代表Java方法,它是由操作码的单字节指令组成的序列,每一个操作码后都跟有一个或多个操作数,即验证是否有合法的操作数)
Ø 二进制兼容性的验证:确保相互引用的类之间协调一致。(例如在Work类中调用了Car类的run方法,在验证Worker类时就会验证Car类中是否有run方法,如果没有则报NoSuchMethodError错误)
14、类的准备和解析
A、类的准备:java虚拟机为类的静态变量分配内存,并设置默认的初始值。
B、类的解析:Java虚拟机会把类的二进制数据中的符号引用替换为直接引用。
(在Worker类的二进制数据中,包含了一个对Car类的run方法的符号引用,在解析阶段,java虚拟机会把这个符号引用替换为一个指针,指向Car类的run方法在方法区内的内存位置,这个指针就是直接引用)
15、类的初始化步骤:
A、假如这个类没有被加载和连接,就先进行加载和连接
B、假如类存在直接的父类,并且这个父类没有被初始化,那先初始化直接父类
C、假如类中存在初始化语句,那就依次的执行这些初始化语句。
16、类的初始化的时机
A、调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。
B、只有当程序访问的静态变量或静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用
17、类的加载父类委托机制(更好的保证java平台安全??):
在父类委托机制中,除了java虚拟机自带的根类加载器,其余的类加载器有且只有一个父类加载器。(当Java程序请求加载器Load1加载Sample类时,Load1会首先委托其父类加载器进行加载,如果父类加载器不能对Sample进行加载,则由Load1进行加载。)
A、优点:提高了软件系统的安全性。在此机制下,用户自定义的类加载器不可能加载应由其父类加载器加载的可靠类,从而防止了不可靠甚至恶意的代码代替父类加载器加载可靠代码。(例如其他由任意用户自定义的类加载器不可能加载含有恶意代码的java.lang.Object类)
18、类加载器:
A、根类加载器(Bootstrap):该类加载器没有父类加载器,它负责加载虚拟机的核心类库,如Java.lang.*等。(java.lang.Object就是由根类加载器进行加载的。根类加载器从系统属性sun.boot.class.path中指定的目录中加载类库。根类加载器的实现依赖于底层操作系统,属于虚拟机的一部分,它并没有继承java.lang.ClassLoader类)
B、扩展类加载器(Extension):它的父类加载器为根类加载器,它从java.ext.dirs系统属性指定的目录或jre\lib\ext中加载类库。(如果把用户创建的JAR放在这个目录下,也会由扩展类加载器进行加载,扩展类加载器是纯JAVA类,它是java.lang.ClassLoader的子类)
C、系统类加载器(System):也称为应用类加载器,它的父类加载器为扩展类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,它是用户自定义的类加载器的默认的父类加载器。系统类加载器是纯java类,是java.lang.ClassLoader的子类。
19、类的命名空间:
每个加载器都有自己的命名空间。这个命名空间由该类加载器及所有的父类加载器所加载的类组成。在同一命名空间中,不会出现类的完整名字相同的两个类;在不同的命名空间有可能出现。
20、JVM内存管理机制
内存空间划分为:堆、JVM方法栈、方法区、本地方法栈、PC寄存器
A、堆:堆用于存储对象实例及数组值。Java中所有通过new创建的对象的内存都在这里分配,heap中对象所占的内存由GC进行回收。(32位OS最大为2GB,64位没有限制,-Xms -Xmx)
B、JVM方法栈:为线程私有,其在内存分配上非常高效,当方法运行完毕时,其对应的栈帧占用的内存也会被自动释放。(JVM方法栈空间不足时,会抛出StackOverflowError,可通过-Xss指定大小)
C、方法区:要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的变量、类中的field信息、类中的方法信息。(最小16M,最大为64M,通过-XX:PerSize -XX:MaxPermSize)
D、本地方法栈:用于支持native方法的执行,存储每个native方法调用的状态。在SUN JDK的实现中和JVM方法栈是同一个。
E、PC寄存器:占用的可能为CPU寄存器或操作系统内存
21、java堆和栈的区别:内存划分为堆内存和栈内存
A、在函数中定义和一些基本类型的变量和对象的引用变量都在函数的栈内存中进行分配。(当定义变量时,JAVA就在栈内存中为其分配内存空间,当超过变量的作用域后,java会自动释放该变量占用的内存)
B、堆内存用来存放由new创建的对象和数组。在堆中分配的内存,Java虚拟机自动的进行垃圾回收管理。(在栈中定义一个特殊变量,让这个变量的取值等于数组或对象在堆内存中的首地址,在栈中的这个变量就变成了数组或对象的引用变量)
C、
22、java内存泄露和内存溢出
A、内存泄露:分配出去的内存回收不了
B、内存溢出:指系统的内存不够用
23、JVM工作原理
A、创建JVM装载环境和配置:JVM提供的方式是操作系统的动态连接文件。(首先查找JRE路径,java通过getApplicationHome获得java.exe的绝对路径,然后判断/jre、\bin下面哪个存在java.dll,如果存在就把其中一个做为JRE的路径。)
B、装载JVM.dll:通过前面得到了JVM的路径,java通过LoadJavaVM来装入JVM.dll文件,装入方式是通过WindowAPI函数来实现的。(LoadLibrary装载JVM.dll动态库,然后把JVM.dll函数中导出的JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunction的这两个函数指针变量上,jvm.dll装载工作宣告完成)
C、初始化JVM.dll并挂界到JNIENV实例( 初始化JVM,获得本地接口,这样就可以在java中调用JVM函数了。调用Invacation-->CreateJavaVM也就是JVM的JNI_CreateJavaVM来获得JNIEnv的实例)
D、调用JNIEnv实例装载并处理class类。
(运行java程序:一种是JAR包,一种是.class文件。前者java -jar xxx.jar运行的时候,java.exe调用GetMainClassName函数,该函数获得JNIEnv实例然后调用java类java.util.jar.JarFileJNIEnv中的方法getMainfest()并返回Mainfest对象中取得getAttributes("Main-Class")的值即jar包中的META-INF/MANIFEST.MF指定的主类名运行主类,之后main函数会调用java.c中的loadClass方法装载该类。然后main函数调用JNIEnv实例getStaticMethodID方法查找主类中的main(String[] args),并判断该方法是否为public方法,然后调用JNIEnv实例的CallStaticvoidMethod调用java类的main方法)
参考文档:
深入理解JVM :http://www.iteye.com/topic/752755
深入剖析JVM原理及特点:http://blog.csdn.net/harry0514/article/details/5939459