几个重要的概念:

java进程 -- 当启动一个java程序时,操作系统为进程分配资源,包括内存空间等

jvm -- java进程中必须存在的部分,通俗的说,即启动java程序时,jvm也就启动了,java字节码运行在jvm的管理之中

native method -- java跨平台的同时也损失了一些性能,native method使得java可以调用别的语言实现的一些功能模块,如C/C++写的.dll/.so,这些方法的实现代码运行在JVM之          外,所以内存的管理由程序员自己负责,如果这部分程序有内存泄漏,也会造成java进程的内存一直增长。

动态链接库 -- linux 下形如 libx.so, windows下形如libx.dll

jvm内存管理模型

在jvm中内存可分为两大类,线程共享内存和线程私有内存。

  1. 线程共享内存包括:
    • Method Area
      • 方法区,这部分存储的是jvm加载的class的信息,常量,静态变量,即时编译器编译后的代码等
    • Java Heap
      • java堆,这部分区域是java的所有对象实例,数组等的所在
  2. 线程私有内存区:
    • Program Counter Register
      • 程序计数寄存器,每个线程有自己的技术寄存器,存储当前线程执行字节码的地址
    • JVM Stack
      • jvm栈区,每启动一个线程,jvm就为该线程分配一个栈区,线程调用方法时和方法返回时会进行入栈和出栈操作
    • Native Stack
      • 本地方法栈区,与jvm stack类似,不过此区域是为调用本地方法服务的

JDK1.4引入了NIO,出现了一个新的内存概念,DirectMemory(直接内存),它并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域。

在NIO中,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,他可以使用Native函数库直接分配对外内存,然后通过存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样在一些场合下避免了在java堆和Native堆中来回复制数据,从而提高性能。

 

Jvm的垃圾收集器GC主要运行于Java Heap中,根据具体的垃圾收集策略,回收堆中对象所占空间,具体的垃圾收集策略以后有时间再补充

而在Method Area中,GC也会回收一些没有用的Class信息,但判断一个类信息没用的条件非常苛刻。在一些框架中,例如Spring、Struts等,由于使用动态代理和反射机制,会有大量的类信息,如果Method Area的大小设置较低,会抛出OutOfMemoryError(内存溢出错误异常)。此区域大小设置见下文。

在栈区,当线程结束后,GC也会收集其所占用的栈区内存空间

 

上述内存区域的大小理论上都是可以在JVM启动时加入参数来设置的,具体是否有效要看具体实现

以最典型的sun的hotspot为例

 -Xms20M 最小堆内存设置为20M,据说默认为物理内存的1/64

 -Xmx40M 最大堆内存设置为40M,默认为物理内存的1/4

 -Xss2M 设置栈区的大小,-Xoss理论上是可以设置本地方法栈的大小,但实际上是无效的,因为hotspot不区分JVM stack 和 Native Stack

 -XX:PermSize=20M 设置方法区的初始大小,默认为物理内存的1/64

 -XX:MaxPermSize=30M 设置方法区的最大值,默认为物理内存的1/4

还有的说法是,MaxPermSize缺省值和-server -client选项相关。

  -server选项下默认MaxPermSize为64m 

  -client选项下默认MaxPermSize为32m

note:-server即运行服务器程序,jvm会进行一些优化;-client是以客户端程序运行,默认为-client

直接内存也会溢出,可以通过 -XX:MaxDirectMemorySize=10M 来设置,默认和-Xmx一样,具体参见book 《深入理解Java虚拟机》 周志明著

 

 


 

 

posted on 2012-03-13 20:57  shosciation  阅读(563)  评论(0编辑  收藏  举报