java虚拟机 JVM
来源:互联网 发布:图像对比识别软件 编辑:程序博客网 时间:2024/06/14 02:42
造成栈溢出的几种情况:
1)递归过深
2)数组、List、map数据过大
可使用以下代码造成堆栈溢出:
package overflow;
import java.util.ArrayList;
/**
* Created by hupo.wh on 2016/7/7.
*/
public class MyTest {
public void testHeap(){
for(;;){
ArrayList list = new ArrayList (2000);
}
}
int num=1;
public void testStack(){
num++;
this.testStack();
}
public static void main(String[] args){
MyTest t = new MyTest();
t.testHeap();
//t.testStack();
}
}
如下代码会造成OOM堆溢出:
package OOM;
import java.util.ArrayList;
import java.util.List;
/**
* Created by hupo.wh on 2016/7/15.
*/public class App1 {
static class OOMClass {
long[] num = new long[10240];
}
public static void main(String[] args) {
List<OOMClass> list = new ArrayList<>();
while (true) {
list.add(new OOMClass());
}
}
}
java –Xms128m //JVM占用最小内存
–Xmx512m //JVM占用最大内存
–XX:PermSize=64m //最小堆大小
Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能。
在加载阶段,虚拟机主要完成三件事:
2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。
验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。如果验证失败,就会抛出一个java.lang.VerifyError异常或其子类异常。验证过程分为四个阶段:
2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。
3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。
准备:
准备阶段为变量分配内存并设置类变量的初始化。在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。对非final的变量,JVM会将其设置成“零值”,而不是其赋值语句的值:
private static int size = 12;
思想:
通过一系列称为 GC Roots 的对象作为起始点,从这些点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链连接(用图论的话来说,就是从GC Roots到这个对象不可达),证明此对象不可用。
Java语言中,可作为GC Roots的对象包括:
(1)虚拟机栈(栈帧中的本地变量表)中引用的对象
(2)方法区中类静态属性引用的对象
- root搜索算法
这种算法目前定义了几个root,也就是这几个对象是jvm虚拟机不会被回收的对象,所以这些对象引用的对象都是在使用中的对象,这些对象未使用的对象就是即将要被回收的对象。简单就是说:如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收。
以下对象会被认为是root对象:
- 被启动类(bootstrap加载器)加载的类和创建的对象
- jvm运行时方法区类静态变量(static)引用的对象
- jvm运行时方法去常量池引用的对象
- jvm当前运行线程中的虚拟机栈变量表引用的对象
- 本地方法栈中(jni)引用的对象
1、 对象没有引用
2、 作用域发生未捕获异常
3、 程序在作用域正常执行完毕
在JDK 1.2之后 ,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference )、软引用(Soft Reference )、弱引用(Weak Reference )、虚引用(Phantom Reference) 4种 , 引用强度依次逐渐减弱。
强引用
指在程序代码之中普遍存在的,类似“Object obj=new Object ( ) ”这类的引用 ,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
1.3.6 垃圾收集算法
1.3.6.1 标记-清除算法
望名生意,算法分为“标记”和“清除”两个阶段:
首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象,它的标记过程如前
它的主要不足有两个:
(1)效率问题,标记和清除两个过程的效率都不高;
(2)空间问题,标记清除之后会产生**大量不连续的内存碎片**,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
1.3.6.2 复制算法
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
适用于对象存活率低的场景(新生代)
这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针 ,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为了原来的一半,未免太高了一点。
将内存分为**一块较大的Eden空间和两块较小的Survivor空间** ,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次地复制到另外一块Survivor空间上,最 后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用内存空间为整个新生代容量的90% ( 80%+10% ) ,只有10% 的内存会被 “浪费”。当然,98%的对象可回收只是一般场景下的数据,我们没有办法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保( Handle Promotion ) 。
1.3.6.3 标记-整理算法
适用于对象存活率高的场景(老年代)
复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。更关键的是 ,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。
标记过程类似“标记-清除”算法,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,类似于磁盘整理的过程
总的分类如下图:
2.装载JVM.dll
3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例
- JVM(JAVA虚拟机介绍)
- JVM(JAVA虚拟机介绍)
- JVM(JAVA虚拟机介绍)
- JVM(JAVA虚拟机介绍)
- JVM(JAVA虚拟机介绍)
- JVM(JAVA虚拟机)
- Java虚拟机(JVM)
- JVM(JAVA虚拟机介绍)
- JVM(JAVA虚拟机)
- Java虚拟机学习心得(JVM)
- java虚拟机JVM
- 初学java虚拟机-JVM
- java虚拟机JVM 移植
- Java 虚拟机(JVM)介绍
- Java虚拟机JVM
- Java 虚拟机 JVM
- java虚拟机之JVM
- java虚拟机JVM总结
- 【翻译】DPI and Device-Independent Pixels
- OpenCV学习之Canny边缘检测
- 图像处理13:物体追踪
- c++写时拷贝
- UnicodeDecodeError: 'gbk' codec can't decode byte 0xfe in position 45: illegal multibyte sequence
- java虚拟机 JVM
- 注释转换(C到C++的注释转换)
- 课堂学习——HDUOJ-1452
- java中求最大公约数和最小公倍数的方法
- Angular 设置input[number] 的初始值和双向绑定的使用
- linux学习之旅(十三)&& 系统虚拟机管理
- API学习IdentityHashMap
- leetcode 650. 2 Keys Keyboard
- leetcode-7.30