java内存划分
共享内存区域
方法区
堆
线程隔离内存区域
程序计数器
每个线程都有独立的程序计数器,用于取指,分支,跳转,循环,恢复线程等操作
PC=PC+1(指令字节长)
如果线程执行的是一个java方法,则这个计数器记录的是虚拟机字节码指令;如果线程执行的是一个native方法,则这个计数器值为空,此内存区域是唯一一个在java虚拟机规范中没有规定任何OOMError的区域
native方法:即不是由Java实现,而是由其他语言实现的方法
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
可以将native方法比作Java程序同C程序的接口,其实现步骤:
1、在Java中声明native()方法,然后编译。
2、用javah产生一个.h文件。
3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件)。
4、将第三步的.cpp文件编译成动态链接库文件。
5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
JAVA的native方法适用的情况:
1、为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问。
2、为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的。
3、为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
虚拟机栈
生命周期与java线程相同,存放 局部变量表,操作数栈,动态链接,方法出口等信息
局部变量表所需内存空间在编译时确定,而不会在运行时修改,所以,此区域会有两种异常
- StackOverFlowError
线程请求栈的深度超过虚拟机所允许的深度 - OutOfMemoryError
栈动态扩展到无法申请到足够的内存
扩展:
-Xmx3550m:设置JVM最大可用内存为3550M。
-Xms3550m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2g:设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
1 java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
-XX:MaxPermSize=16m:设置持久代大小为16m。
-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
本地方法栈
服务于native方法
Java堆
java虚拟机中最大的一块内存部分,用于存放对象实例
方法区
存放虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等
运行时常量池:存放编译器生成的各种字面量与符号引用
这里讲的java常量池很详细
符号引用:
直接引用:
运行时也可以将新的常量放到常量池
直接内存
堆外内存,NIO支持直接分配对外内存