虚拟机运行时数据区
线程共享
java Heap
java heamp是java虚拟机可配置管理的最大内存区;唯一的目的用于存储实例对象,所有线程共享;
GC堆,回收技术主要采用分代收集算法;java Heap细分为:新生代、老生代;划分本身与存放内容无关;无论怎么划分,都是为了更好的分配和回收内存;
逻辑上连续,物理上未必连续;
利用-Xms、-Xmx进行配置,无法分配及扩展时,将会抛出OutOfMerroyError错误;
method area
存储对象:虚拟机加载的类信息、常量、静态变量、JIT编译器编译后的代码
alias name: Non-Heap
HotSpot虚拟机,Permanent Generation(永久代),实际上两者并不等价,将GC扩展到方法区;
线程隔离
native method stack
program counter register
线程私有;
java虚拟机多线程通过线程轮流切换并分配处理器执行时间;
多线程轮流切换,必然需要在某刻恢复线程在上次执行的执行地址;例如一个线程在执行一个方法,计数器记录就是线程执行的虚拟机字节码指令的地址;如果是Native方法,那么计数器的值为空(undefined)
唯一一个无OutOfMemoryError的内存
vms stack
直接内存
direct memory, 并非是虚拟机运行时数据区的一部分;
NIO(new input/output), channel+buffer新型IO,利用Native函数库直接分配堆外内存;利用存储在java-heap中的DirectByteBuffer对象对该块内存进行直接引用操作;优点是避免在java-heap和native-heap之间进行来回复制数据
OutOfMerroyError错误;
对象
内存分配方式
指针碰撞(bump the pointer)---ParNew、Serial
空闲列表(Free List) --- CMS(Mark-Sweep)
决定条件
垃圾收集器是否带有压缩整理==>java-heap是否规整
内存分配策略
目的:解决冲突问题
方法一:CAS + 错误重试===>保证更新操作的原子性
方法二:线程在不同的空间预分配内存(java-heap),预分配内存称之为TLAB(Thread Local Allocation Buffer),那个线程需要分配内存,就在那个线程的TLAB上分配,只有TLAB用光后分配新的TLAB时,才需要同步锁定;虚拟机是否使用TLAB,通过-XX:+/-UseTLAB参数配置;
内存布局
header、Instance Data、Padding(对齐填充)
header: 对象的HashCode\偏向线程ID\GC分代年龄\锁状态标志\类型指针(对象指向它的类元数据的指针)
Padding无真实意义;保证数据长度是8字节的整数倍
Instance Data: 父类和子类可能会交叉存储,较小的子类变量可能会插入到父类变量的空隙之中;相同长度的字段总被分配到一起,如:shorts/chars、longs/doubles
对象访问
句柄、直接指针
区别
句柄方式访问数据 --- reference(句柄地址)-->句柄池(存放数据指针)--->对象指针-->数据
直接指针 ----reference(对象指针地址)-->对象指针-->数据
JVM Error
java-heap配置
-Xms(堆最小), -Xmx(堆最大)
不可扩展:设置相同
-XX:+HeapDumpOnOutOfMemoryError: 当出现内存溢出异常时,Dump出当前的内存堆的存储快照
分类
堆溢出
memory leak(内存泄露)
memory overflow(内存溢出)
栈溢出(虚拟机、本地方法)
-Xss决定
出现场景
线程请求栈深度>虚拟机允许深度 -->StackOverfolwError
虚拟机在扩展栈时未申请到足够内存 -->OutOfMemoryError
方法区、运行时常量池
-XX:PermSize -XX:MaxPermSize
String.intern(),Native方法,作用:如果常量池中有对应String对象,那么返回;如果没有,将对应的字符串放入常量池;具体用法:String.ValueOf(i++).intern()
直接内存
-XX:MaxDirectMemorySize,如果不指定,默认等于-Xmx取值相同
posted @
2017-05-21 00:09
征途2
阅读(
163 )
评论()
编辑
收藏
举报