auto commit

This commit is contained in:
CyC2018 2018-04-02 20:42:30 +08:00
parent 5ad1c6f7e5
commit 4e597e3f10
3 changed files with 24 additions and 25 deletions

View File

@ -1,9 +1,9 @@
<!-- GFM-TOC -->
* [一、运行时数据区域](#一运行时数据区域)
* [程序计数器](#程序计数器)
* [Java 虚拟机栈](#java-虚拟机栈)
* [虚拟机栈](#虚拟机栈)
* [本地方法栈](#本地方法栈)
* [Java 堆](#java-堆)
* [堆](#堆)
* [方法区](#方法区)
* [运行时常量池](#运行时常量池)
* [直接内存](#直接内存)
@ -27,17 +27,17 @@
# 一、运行时数据区域
<div align="center"> <img src="../pics//JVM-runtime-data-area.jpg" width=""/> </div><br>
<div align="center"> <img src="../pics//540631a4-6018-40a5-aed7-081e2eeeaeea.png" width="500"/> </div><br>
## 程序计数器
记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空)。
## Java 虚拟机栈
## 虚拟机栈
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
<div align="center"> <img src="../pics//JVM-Stack.png" width=""/> </div><br>
<div align="center"> <img src="../pics//f5757d09-88e7-4bbd-8cfb-cecf55604854.png" width=""/> </div><br>
可以通过 -Xss 这个虚拟机参数来指定一个程序的 Java 虚拟机栈内存大小:
@ -56,9 +56,9 @@ java -Xss=512M HackTheJava
与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法服务。
<div align="center"> <img src="../pics//JNIFigure1.gif" width="400"/> </div><br>
<div align="center"> <img src="../pics//JNIFigure1.gif" width="350"/> </div><br>
## Java
## 堆
所有对象实例都在这里分配内存。
@ -102,7 +102,7 @@ Class 文件中的常量池(编译器生成的各种字面量和符号引用
## 直接内存
在 JDK 1.4 中新加入了 NIO 类,引入了一种基于通道Channel与缓冲区Buffer的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
在 JDK 1.4 中新加入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
# 二、垃圾收集
@ -221,11 +221,9 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
不足:
1. 标记和清除过程效率都不高
1. 标记和清除过程效率都不高
2. 会产生大量碎片,内存碎片过多可能导致无法给大对象分配内存。
之后的算法都是基于该算法进行改进。
### 2. 复制
<div align="center"> <img src="../pics//e6b733ad-606d-4028-b3e8-83c3a73a3797.jpg" width=""/> </div><br>
@ -394,7 +392,7 @@ JVM 为对象定义年龄计数器,经过 Minor GC 依然存活,并且能被
### 4. 动态对象年龄判定
JVM 并不是永远地要求对象的年龄必须达到 MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 区中相同年龄所有对象大小的总和大于 Survivor 空间的一半,则年龄大于或等于该年龄的对象可以直接进入老年代,无等待 MaxTenuringThreshold 中要求的年龄。
JVM 并不是永远地要求对象的年龄必须达到 MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 区中相同年龄所有对象大小的总和大于 Survivor 空间的一半,则年龄大于或等于该年龄的对象可以直接进入老年代,无等待 MaxTenuringThreshold 中要求的年龄。
### 5. 空间分配担保
@ -418,7 +416,7 @@ JVM 并不是永远地要求对象的年龄必须达到 MaxTenuringThreshold 才
### 4. JDK 1.7 及以前的永久代空间不足
在 JDK 1.7 及以前HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 class 的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么 JVM 会抛出 java.lang.OutOfMemoryError为避免以上原因引起的 Full GC可采用的方法为增大永久代空间或转为使用 CMS GC。
在 JDK 1.7 及以前HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么 JVM 会抛出 java.lang.OutOfMemoryError为避免以上原因引起的 Full GC可采用的方法为增大永久代空间或转为使用 CMS GC。
### 5. Concurrent Mode Failure
@ -448,7 +446,7 @@ JVM 并不是永远地要求对象的年龄必须达到 MaxTenuringThreshold 才
虚拟机规范中并没有强制约束何时进行加载,但是规范严格规定了有且只有下列五种情况必须对类进行初始化(加载、验证、准备都会随着发生):
1. 遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时,如果类没有进行过初始化,则必须先触发其初始化。最常见的生成这 4 条指令的场景是:使用 new 关键字实例化对象的时候;读取或设置一个类的静态字段(被 final 修饰、已在编译把结果放入常量池的静态字段除外)的时候;以及调用一个类的静态方法的时候。
1. 遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时,如果类没有进行过初始化,则必须先触发其初始化。最常见的生成这 4 条指令的场景是:使用 new 关键字实例化对象的时候;读取或设置一个类的静态字段(被 final 修饰、已在编译把结果放入常量池的静态字段除外)的时候;以及调用一个类的静态方法的时候。
2. 使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行初始化,则需要先触发其初始化。
@ -507,19 +505,19 @@ System.out.println(ConstClass.HELLOWORLD);
主要有以下 4 个阶段:
**(一)文件格式验证**
(一)文件格式验证
验证字节流是否符合 Class 文件格式的规范,并且能被当前版本的虚拟机处理。
**(二)元数据验证**
(二)元数据验证
对字节码描述的信息进行语义分析,以保证其描述的信息符合 Java 语言规范的要求。
**(三)字节码验证**
(三)字节码验证
通过数据流和控制流分析,确保程序语义是合法、符合逻辑的。
**(四)符号引用验证**
(四)符号引用验证
发生在虚拟机将符号引用转换为直接引用的时候,对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验。
@ -634,7 +632,7 @@ public static void main(String[] args) {
```java
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//check the class has been loaded or not
// 先检查请求的类是否已经被加载过了
Class c = findLoadedClass(name);
if(c == null) {
try{
@ -644,9 +642,10 @@ protected synchronized Class<?> loadClass(String name, boolean resolve) throws C
c = findBootstrapClassOrNull(name);
}
} catch(ClassNotFoundException e) {
//if throws the exception , the father can not complete the load
// 如果父类加载器抛出 ClassNotFoundException说明父类加载器无法完成加载请求
}
if(c == null) {
// 如果父类加载器无法完成加载请求,再调用自身的 findClass() 来进行加载
c = findClass(name);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB