虚拟机的五大核心
方法区、堆内存、栈内存、本地方法栈、程序计数器
方法区:数据被所有线程共享,存放着静态方法,类信息和静态常量 方法区的内存回收主要针对于常量池的回收和类型卸载上
常量池—-是方法区的一部分 class文件中除了类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池里存放
堆内存:数据被所有线程共享,存放着对象的地址值。常说的 new的对象在堆内存中 堆是被所有线程共享,虚拟机启动时创建,几乎创建所有的对象实例都在堆内存中,创建此内存区域的唯一目的就是存放对象实例,现在也可能是栈上分配、标量替换(其原因是如果只有一个main方法是用了某个对象,而其他地方没有被再次使用,他就会在栈内存分配 现在收集器基本都采用分的收集算法,所以对于堆中还可以细分为新生代和老年代 堆可以处于物理上部连续的内存空间中,只要逻辑上是连续的即可。
修改jvm堆内存参数(-Xmx和-Xms)
如果在堆中没有内存完成实例分配,并且堆内存无法拓展(扩容)时,会爆出内存溢出异常
栈内存 :数据被线程隔离、存放着局部变量、对象的引用地址值 字节码地址值
本地方法栈:存放的是java调用的本地系统资源API
程序计数器:每一个线程,用来控制执行程序的下一行指令(出入方法 报错 )
对象的创建
虚拟机在遇到new关键字的时候,会先去检查这个指令的参数能否在常量池中找到一个类的符号引用,并且检查这个类是否已经被加载、解析、初始化,如果没有就会进行相应的类加载,随后将为新对象分配内存
内存分配方式及原理
指针碰撞:堆内存是相对规整的、用过的内存在一边,没有用过的在另外一边,中间用指针做标识 空闲列表:堆内存是散列的,需要做内存补充的
对象的内存布局
对象在内存中的布局主要分为三个部分
object header (对象头)
instance data (实例数据)
对齐填充(当前对象占用的字节 8/8的倍数 )