Java虚拟机

摘自: http://www.ibm.com/developerworks/cn/java/j-lo-jvm-perf/ 

 

JVM 的实现

Sun Hotspot、IBM J9、Oracle JRockit

 

 

 

 一. Java 堆和栈

 

 

  1. 类装载子系统:通过类的全限定名(包名和类名,网络装载还包括 URL)将 Class 装载进运行时数据区;
  2. 方法区:Class 对于所有方法和 static 静态数据的定义存储在这里,它就像一张表或数组,让程序执行时在这里找到相应方法的 Java 字节码和静态数据;
  3. Java 堆:Java 对象的持久化存储区,从类实例化而来的对象存储在此,垃圾收集也在此进行,若是空间不够容纳当前所有对象,Out Of Memory 的异常将会抛出,对 Java 堆和垃圾收集的认识对应用性能调优很关键;        创建的 Java 对象(包括数组,数组也是一种对象)分配在堆中,垃圾收集对象来释放空间; 最常设置的堆大小参数有:-Xms,设置堆的初始大小;-Xmx,设置堆空间的最大值;-Xmn,设置年轻代空间大小;-Xmo,设置年老代空间大小 
  4. Java 栈:Java 方法的字节码执行的地方,方法中局部变量的生命周期都在栈中,栈的大小是我们要考虑的一个关键点,它直接决定了方法调用的层数,这对递归程序来说尤为重要。我们所用的 JVM 都是基于 Java 栈的运行机制,而有一个例外的实现,Google 移动设备操作系统 Android 的虚拟机 Dalvik 则是基于寄存器的机制(Dalvik 虽然支持 Java 语言开发,但从虚拟机的角度看,并不符合 Java 标准),关于虚拟机实现时,栈和寄存器机制的比较,请参考论文“Virtual Machine Showdown: Stack Versus Registers”; 栈划分为操作数栈、栈帧数据和局部变量区,方法中分配的局部变量在栈中,同时每一次方法的调用都会在栈中分配栈帧. 对于基于栈的 Java 虚拟机,方法的调用和执行伴随着压栈和出栈操作。每个线程有各自独立的栈,由虚拟机来管理栈的大小,但我们应该对它的大小有个概念。栈的大小是把双刃剑,如果太小,可能会导致栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更大,如果过大,就会影响到可创建栈的数量,如果是多线程的应用,就会导致内存溢出。通过 -Xss可以设置 Java 栈的最大值,默认值为 256K
  5. 程序计数器:对于基于栈实现的 JVM,这几乎是唯一寄存器了,它用来指示当前 Java 执行引擎执行到哪条 Java 字节码,指针指向方法区的字节码;
  6. 本地方法栈:这是 Java 调用操作系统本地库的地方,用来实现 JNI(Java Native Interface,Java 本地接口);
  7. 执行引擎:JVM 的心脏,控制装入 Java 字节码并解析;
  8. 本地接口:连接了本地方法栈和操作系统库。

 

二.  Java内存泄漏例子

 

   下面的pop1会引起内存泄漏

 public class Stack { 
  private static final int MAXLEN = 10; 
  private Object stk[] = new Object[MAXLEN]; 
  private int stkp = -1; 

  public void push(Object p) { 
    stk[++stkp] = p; 
  } 
 
  public Object pop1() { 
    return stk[stkp--]; 
  } 
  
  public Object pop2() { 
    Object p = stk[stkp]; 
    stk[stkp--] = null;
    return p; 
  } 
 } 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值