Java虚拟机JVM
java虚拟机运行时数据区
方法区(Method area):
属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。堆区(Heap):
线程共享,主要是存放对象实例和数组。
内部会划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB)。 可以位于物理上不连续的空间,但是逻辑上要连续。
OutOfMemoryError
:如果堆中没有内存完成实例分配,并且堆也无法再扩展时,抛出该异常。虚拟机栈(VM Stack):
线程私有,生命周期和线程一致。
描述的是 Java 方法执行的内存模型 每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。
StackOverflowError
:线程请求的栈深度大于虚拟机所允许的深度。
OutOfMemoryError
:如果虚拟机栈可以动态扩展,而扩展时无法申请到足够的内存。本地方法栈(Native Method Stack):
区别于 Java 虚拟机栈的是,Java 虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。
也会有 StackOverflowError 和 OutOfMemoryError 异常。程序计数器(Program Counter Register):
内存空间小,线程私有。
字节码解释器工作是就是通过改变这个计数器的值来选取下一条需要执行指令的字节码。
指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。
堆区内存划分
堆区 = 新生代 + 老生代
新生代= Eden区 + Survivor区(from)+ Survivor区(to)
老生代= Tentured区
默认的
新生代:老生代= 1:2
Eden:from:to = 8:1:1
所谓的新生代和老年代是针对于分代收集算法来定义的。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。
因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间;
GC 分为两种:老生代中采用标记-清除算法的Full GC ( 或称为 Major GC )和新生代中采用复制算法的Minor GC。新生代是 GC 收集垃圾的频繁区域;
如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空 间当中。并将其年龄设为1,对象在Survivor每熬过一
次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代 中了,当然晋升老年代的年龄是可以设置的。
其实新生代和老年代就是针对于对象做分区存储,更便于回收
JVM的参数配置
- 第一组配置参数(堆区):
-Xms 、-Xmx、-XX:newSize、-XX:MaxnewSize、-Xmn
所谓堆区即为通过new的方式创建的对象(类实例)所占用的内存空间
-Xms :
表示java虚拟机堆区内存初始内存分配的大小,通常为操作系统可用内存的1/64大小即可
-Xmx:
表示java虚拟机堆区内存可被分配的最大上限,通常为操作系统可用内存的1/4大小(但是开发过程中,通常会将 -Xms 与 -Xmx两个参数的配置相同的值)
-Xmn:
表示新生代的大小
- 第二组配置参数(非堆区):
非堆区即为代码、常量、外部访问(如文件访问流所占资源)等
在配置之前一定要慎重的考虑一下自身软件所需要的非堆区内存大小
-XX:PermSize:
表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存)
-XX:MaxPermSize:
表示对非堆区分配的内存的最大上限。
- 配置自定义jvm属性
-Dvar1=123456 \
-Dvar4encoding=GBK"
-D固定写法,后面加变量名称
var1变量名称,程序可以通过System.getProperty(“var”)获取该值
如果有多行在值的后面加空格,加斜杆,表示换行
如果是最后一行在值的后面直接加双引号,不要加空格