-
虚拟机运行时数据区
- 线程共享
- java Heap
- java heamp是java虚拟机可配置管理的最大内存区;唯一的目的用于存储实例对象,所有线程共享;
- GC堆,回收技术主要采用分代收集算法;java Heap细分为:新生代、老生代;划分本身与存放内容无关;无论怎么划分,都是为了更好的分配和回收内存;
- 逻辑上连续,物理上未必连续;
- 利用-Xms、-Xmx进行配置,无法分配及扩展时,将会抛出OutOfMerroyError错误;
- method area
- 存储对象:虚拟机加载的类信息、常量、静态变量、JIT编译器编译后的代码
- alias name: Non-Heap
- HotSpot虚拟机,Permanent Generation(永久代),实际上两者并不等价,将GC扩展到方法区;
- java Heap
- 线程隔离
- 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不用动
- 直接指针 ----reference(对象指针地址)-->对象指针-->数据
- 优势:访问数据块
- 句柄方式访问数据 --- reference(句柄地址)-->句柄池(存放数据指针)--->对象指针-->数据
- 内存分配方式
-
JVM Error
- java-heap配置
- -Xms(堆最小), -Xmx(堆最大)
- 不可扩展:设置相同
- -XX:+HeapDumpOnOutOfMemoryError: 当出现内存溢出异常时,Dump出当前的内存堆的存储快照
- -Xms(堆最小), -Xmx(堆最大)
- 分类
- 堆溢出
- memory leak(内存泄露)
- memory overflow(内存溢出)
- 栈溢出(虚拟机、本地方法)
- -Xss决定
- 出现场景
- 线程请求栈深度>虚拟机允许深度 -->StackOverfolwError
- 虚拟机在扩展栈时未申请到足够内存 -->OutOfMemoryError
- 方法区、运行时常量池
- -XX:PermSize -XX:MaxPermSize
- String.intern(),Native方法,作用:如果常量池中有对应String对象,那么返回;如果没有,将对应的字符串放入常量池;具体用法:String.ValueOf(i++).intern()
- 直接内存
- -XX:MaxDirectMemorySize,如果不指定,默认等于-Xmx取值相同
- 堆溢出
- java-heap配置
时间: 2024-10-11 10:01:05