' U6 m3 L6 p C* X7 F当Java程序开始运行时,JVM会从操作系统获取一些内存。JVM使用这些内存,这些内存的一部分就是堆内存。堆内存通常在存储地址的底层,向上排列。当一个对象通过new关键字或通过其他方式创建后,对象从堆中获得内存。当对象不再使用了,被当做垃圾回收掉后,这些内存又重新回到堆内存中。要学习垃圾回收,请阅读”Java中垃圾回收的工作原理”。# y# Z6 \# [5 W. u4 S
; x# d5 O% O5 ? \/ K0 i4 l. b如何增加Java堆空间$ I1 X; j! Y# q8 O
' F* M5 M" [ V2 t3 g9 `
在大多数32位机、Sun的JVM上,Java的堆空间默认的大小为128MB,但也有例外,例如在32未Solaris操作系统(SPARC平台版本)上,默认的最大堆空间和起始堆空间大小为 -Xms=3670K 和 -Xmx=64M。对于64位操作系统,一般堆空间大小增加约30%。但你使用Java 1.5的throughput垃圾回收器,默认最大的堆大小为物理内存的四分之一,而起始堆大小为物理内存的十六分之一。要想知道默认的堆大小的方法,可以用默认的设置参数打开一个程序,使用JConsole(JDK 1.5之后都支持)来查看,在VM Summary页面可以看到最大的堆大小。 7 d% C6 j' l# N. j: E, u: N7 Z, q' O: U; C! j1 C
用这种方法你可以根据你的程序的需要来改变堆内存大小,我强烈建议采用这种方法而不是默认值。如果你的程序很大,有很多对象需要被创建的话,你可以用-Xms and -Xmx这两个参数来改变堆内存的大小。Xms表示起始的堆内存大小,Xmx表示最大的堆内存的大小。另外有一个参数 -Xmn,它表示new generation(后面会提到)的大小。有一件事你需要注意,你不能任意改变堆内存的大小,你只能在启动JVM时设定它。& {" r y9 x, C3 e6 F1 B5 s$ U
% @* u2 Q6 j. ?! k' Q% m; Z4 m堆和垃圾回收 / F6 ^8 K, T }$ o7 w 3 l7 d2 N; G6 R6 k0 a我们知道对象创建在堆内存中,垃圾回收这样一个进程,它将已死对象清除出堆空间,并将这些内存再还给堆。为了给垃圾回收器使用,堆主要分成三个区域,分别叫作New Generation,Old Generation或叫Tenured Generation,以及Perm space。New Generation是用来存放新建的对象的空间,在对象新建的时候被使用。如果长时间还使用的话,它们会被垃圾回收器移动到Old Generation(或叫Tenured Generation)。Perm space是JVM存放Meta数据的地方,例如类,方法,字符串池和类级别的详细信息。你可以查看“Java中垃圾回收的工作原理”来获得更多关于堆和垃圾回收的信息。 7 N' k( m" `' ~% a8 r9 w" { ; ^* c7 F* O% A, _* Y * r! F7 X+ `" B$ ?, r : R1 w1 Z$ v. u; h* Z4 hJava堆中的OutOfMemoryError错误 1 u; G" Q0 }* T8 j4 p( ~0 y M5 { J: x- q c4 U) O/ H3 c
当JVM启动时,使用了-Xms 参数设置的对内存。当程序继续进行,创建更多对象,JVM开始扩大堆内存以容纳更多对象。JVM也会使用垃圾回收器来回收内存。当快达到-Xmx设置的最大堆内存时,如果没有更多的内存可被分配给新对象的话,JVM就会抛出java.lang.outofmemoryerror,你的程序就会当掉。在抛出 OutOfMemoryError之前,JVM会尝试着用垃圾回收器来释放足够的空间,但是发现仍旧没有足够的空间时,就会抛出这个错误。为了解决这个问题,你需要清楚你的程序对象的信息,例如,你创建了哪些对象,哪些对象占用了多少空间等等。你可以使用profiler或者堆分析器来处理 OutOfMemoryError错误。”java.lang.OutOfMemoryError: Java heap space”表示堆没有足够的空间了,不能继续扩大了。”java.lang.OutOfMemoryError: PermGen space”表示permanent generation已经装满了,你的程序不能再装在类或者再分配一个字符串了。 ( W9 Y- x8 g5 S* k1 m( g+ w& o2 R& ~8 \( ~# ]4 r
Java Heap dump & Q2 q/ _/ \" C7 N N7 w& `0 F 1 C+ q! ]. @9 Q. hHeap dump是在某一时间对Java堆内存的快照。它对于分析堆内存或处理内存泄露和Java.lang.outofmemoryerror错误是非常有用的。在JDK中有一些工具可以帮你获取heap dump,也有一些堆分析工具来帮你分析heap dump。你可以用“jmap”来获取heap dump,它帮你创建heap dump文件,然后,你可以用“jhat”(堆分析工具)来分析这些heap dump。2 x5 b; b0 F7 |9 f _* }* e! c2 v* x
- W% l4 A l" m6 A9 @+ A9 ?
Java堆内存(heap memory)的十个要点' }( w3 O8 v3 m
& z' t/ A3 j2 X6 |1 L1. Java堆内存是操作系统分配给JVM的内存的一部分。 ! h8 O' E& N/ B! g5 T) o3 j8 q0 N2 T1 \( r
2. 当我们创建对象时,它们存储在Java堆内存中。 s- |) I( k+ y2 G
9 B T/ E5 |; W9 A; k
3. 为了便于垃圾回收,Java堆空间分成三个区域,分别叫作New Generation, Old Generation或叫作Tenured Generation,还有Perm Space。0 j( @5 k9 ~& @' q' U! h) `$ m+ t' `
6 ~" P: _# D9 Y* w4. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。不要忘了在大小后面加上”M”或者”G”来表示单位。举个例子,你可以用 -Xmx256m来设置堆内存最大的大小为256MB。 - J# _9 k& k9 u' G- c- z! I6 ?9 {6 w2 D4 b) v2 W
5. 你可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(), Runtime.freeMemory()来查看Java中堆内存的大小。 ' u A5 o" w0 E, }; b3 z. {9 o5 i9 |& h
6. 你可以使用命令“jmap”来获得heap dump,用“jhat”来分析heap dump。% U% E5 x7 U1 |" @5 Q8 F