Java->Class->装载-链接-初始化
编译机制
1. Parse and Enter
Parse 词法分析、语法分析
Enter 将符号输入到符号表
2. Annotation Processing
Lombok @Getter String username; -> String getUsername();
3. Analyse and Generate
Analyse 基于抽象语法树进行语义分析
Gen 生成class
类加载机制
装载
链接
初始化
内存管理
Sun JDK在实现时遵照JVM规范,将内存空间划分为
方法区
方法区存放了要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,Class对象的getName、isInterface等方法都来源于方法区域。
方法区域也是全局共享的,在一定条件下它也会被GC,当方法区域要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
在Sun JDK中这块区域对应Permanet Generation,又称为持久代,默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来指定最小值和最大值。
堆
堆用于存储对象实例及数组值。
其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB;-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB
默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRatio=来指定这个比例;
当空余堆内存大于70%时,JVM会减小Heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRatio=来指定这个比例,
对于运行系统而言,为避免在运行时频繁调整Heap 的大小,通常将-Xms和-Xmx的值设成一样。
新生代(New Generation)
新生代由Eden Space和两块相同大小的Survivor Space(通常又称为S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可通过-XX:SurvivorRatio来调整Eden Space及Survivor Space的大小。SurvivorRatio默认为8,例如当-Xmn设置为10MB时,采用串行GC,eden space即为8MB,两个survivor space各1MB。
旧生代(Old Generation或Tenuring Generation)
用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象,新建的对象也有可能在旧生代上直接分配内存。主要有两种状况(由不同的GC实现来决定):
一种为大对象,可通过在启动参数上设置-XX:PretenureSizeThreshold=1024(单位为字节,默认值为0)来代表当对象超过多大时就不在新生代分配,而是直接在旧生代分配,此参数在新生代采用Parallel Scavenge GC时无效,Parallel Scavenge GC会根据运行状况决定什么对象直接在旧生代上分配内存;
另一种为大的数组对象,且数组中无引用外部对象。
旧生代所占用的内存大小为-Xmx对应的值减去-Xmn对应的值。
本地方法栈
本地方法栈用于支持native方法的执行,存储了每个native方法调用的状态,在Sun JDK的实现中本地方法栈和JVM方法栈是同一个。
PC寄存器和JVM方法栈
每个线程均会创建PC寄存器和JVM方法栈
PC寄存器占用的可能为CPU寄存器或操作系统内存,
JVM方法栈占用的为操作系统内存,
JVM方法栈为线程私有,其在内存分配上非常高效。当方法运行完毕时,其对应的栈帧所占用的内存也会自动释放。
当JVM方法栈空间不足时,会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定其大小
内存回收
强引用
A a=new A();就是一个强引用,强引用的对象只有在主动释放了引用后才会被GC。
软引用(SoftReference)
采用软引用来建立引用的对象,当JVM内存不足时会被回收,因此SoftReference很适合用于实现缓存。
另外,当GC认为扫描到的SoftReference不经常使用时,也会进行回收,存活时间可通过-XX:SoftRefLRUPolicyMSPerMB来进行控制,其含义为每兆堆空闲空间中SoftReference的存活时间,默认为1秒。
Object object=new Object();
SoftReference<Object> softRef=new SoftReference<Object>(object);
object=null;
当需要获取时,可通过softRef.get来获取,值得注意的是softRef.get有可能会返回null。
弱引用(WeakReference)
采用弱引用建立引用的对象没有强引用后,GC时即会被自动释放。
WeakReference的使用方法如下:
Object object=new Object();
WeakReference<Object> weakRef=new WeakReference<Object>(object);
object=null;
当需要获取时,可通过weakRef.get来获取,值得注意的是weakRef.get有可能会返回null。
可传入一个ReferenceQueue对象到WeakReference的构造器中,当object对象被标识为可回收时,执行weakRef.isEnqueued会返回true。
虚引用(PhantomReference)
采用虚引用可跟踪到对象是否已从内存中被删除。
PhantomReference的使用方法如下:
Object object=new Object();
ReferenceQueue<Object> refQueue=new ReferenceQueue<Object>();
PhantomReference<Object> ref=new PhantomReference<Object>(object,refQueue);
object=null;
值得注意的是ref.get永远返回null,当object从内存中删除时,调用ref.isEnqueued()会返回true。
调优工具
jstat -class pid
显示加载class的数量,及所占空间等信息。
C:\Users\Administrator>jstat -class 3988
Loaded Bytes Unloaded Bytes Time
22628 50486.8 0 0.0 40.41
jstat -compiler pid
显示VM实时编译的数量等信息。
C:\Users\Administrator>jstat -compiler 3988
Compiled Failed Invalid Time FailedType FailedMethod
5442 4 0 160.18 1 org/jaxen/expr/DefaultNameStep evaluate
jstat -gc pid
显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。
C:\Users\Administrator>jstat -gc 3988
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
33408.0 34112.0 0.0 4758.9 279424.0 22954.7 699072.0 406620.2 262144.0 181978.0 45 1.556 5 5.653 7.209
jmap pid
打印内存使用的摘要信息
jmap –heap pid
java heap信息
C:\Users\Administrator>jmap -heap 3988
Attaching to process ID 3988, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.6-b01
using thread-local object allocation.
Parallel GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 1310720 (1.25MB)
MaxNewSize = 17592186044415 MB
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 268435456 (256.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 286130176 (272.875MB)
used = 23770864 (22.669662475585938MB)
free = 262359312 (250.20533752441406MB)
8.307709565033784% used
From Space:
capacity = 34930688 (33.3125MB)
used = 4873136 (4.6473846435546875MB)
free = 30057552 (28.665115356445312MB)
13.950873226430582% used
To Space:
capacity = 34209792 (32.625MB)
used = 0 (0.0MB)
free = 34209792 (32.625MB)
0.0% used
PS Old Generation
capacity = 715849728 (682.6875MB)
used = 416379120 (397.09007263183594MB)
free = 299470608 (285.59742736816406MB)
58.16571603139591% used
PS Perm Generation
capacity = 268435456 (256.0MB)
used = 186345512 (177.71292877197266MB)
free = 82089944 (78.28707122802734MB)
69.41911280155182% used
C:\Users\Administrator>
jmap -histo:live pid
统计对象count ,live表示在使用
jmap -histo:live 3988
jmap -histo pid >mem.txt
打印比较简单的各个有多少个对象占了多少内存的信息到重定向的文件
C:\Users\Administrator>jmap -histo 3988 >mem.txt
C:\Users\Administrator>notepad mem.txt
jmap -dump:format=b,file=mem.dat pid
将内存使用的详细情况输出到mem.dat 文件
用jhat命令可以参看
jhat -port 7000 mem.dat 然后使用:http://localhost:7000/查看类相关信息
C:\Users\Administrator>jmap -dump:format=b,file=mem.dat 3988
Dumping heap to C:\Users\Administrator\mem.dat ...
Heap dump file created
C:\Users\Administrator>jhat -port 7000 mem.dat
Reading from mem.dat...
Dump file created Wed Apr 25 12:51:50 CST 2012
Snapshot read, resolving...
Resolving 4512527 objects...
Chasing references, expect 902 dots...............
..................................................
Eliminating duplicate references..................
..................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.