JVM笔记

Java虚拟机运行时的数据区域:
程序计数器:
程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码行号指示器,由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了线程切换后能恢复到正确的位置,每条线程都需要一个独立的程序计数器,此类内存为线程私有;

java虚拟机栈:
与程序计数器一样,java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息,每个方法从调用到执行完成的过程就对应着一个栈帧在虚拟机栈从入栈到出栈的过程。

在java虚拟机中对这个区域规定了两种异常情况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常,如果虚拟机可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

本地方法栈:
与虚拟机栈类似,虚拟机栈用于执行java方法,本地方法栈为虚拟机使用到的Native方法服务,同样会抛出StackOverflowError异常和OutOfMemoryError异常。

java堆:
Java堆是被所有线程共享的一块内存区域,在虚拟机启动的时候创建。此内存区域唯一的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,这个区域是垃圾收集器管理的主要区域,因此又称为GC堆,现在收集器基本都采用分代收集的算法,所以java堆还可细分为新生代和老年代;再细致一点的有Eden空间,From Survivor空间,To Survivor空间。Java堆可以处于物理上不连续的内存空间,如果在堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出OutOfMemoryError异常。

方法区:
方法区与java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。垃圾收集行为很少访问此区域;

常量池:
常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间;

创建对象时内存分配方法有两种,分别是指针碰撞和空闲列表,对象创建时非常频繁的行为,为了保证线程安全有两种解决办法,一种是对分配内存空间的动作进行同步处理,实际上虚拟机采用CAS配上失败重试的方法保证更新操作的原子性;另一种是把分配的动作按照线程划分在不同的空间进行,只有某线程空间满了,需要新的空间时才需要同步锁定。

在HotSpot虚拟机中,对象在内存中存储的布局可以分为三个区域:对象头,实例数据,对齐填充;对象头中包括两部分信息,第一部分是存储对象自身运行时的数据,如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等,对象头的另外一部分是类型指针,虚拟机通过这个来确定对象是哪一个类的实例。接下来的实例数据部分是对象真正存储的有效信息,也就是在程序代码中所定义的各种类型的字段内容。第三部分对齐填充是起到占位符的作用,这是因为HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍。

对象的访问定位:
建立对象是为了使用对象,我们的java程序需要通过栈上的reference数据来操作堆上的具体对象,目前有两种访问方式句柄式和直接指针;

句柄式,java堆会划分一块内存作为句柄池,reference中存储的是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自具体地址信息;如果采用直接指针访问,reference中存储的就是对象地址,这两种方式各有好坏,使用句柄式最大的好处就是reference中存储的是稳定的句柄指针,在对象被移动时只会改变句柄中的实例数据指针,reference本身不需要修改,使用直接指针访问方式最大的好处是速度快,HotSpot采用的是第二种;

内存泄漏与内存溢出:
内存泄露:指程序中动态分配内存给一些临时对象,但对象不会被GC回收,它始终占用内存,被分配的对象可达但已无用。即无用对象持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间浪费

内存溢出:指程序运行中无法申请到足够的内存而导致的一种错误,内存泄露是内存溢出的一种诱因,但不是唯一因素

四种引用类型:
强引用:强引用就是在程序代码中普遍存在的,类似Obiect obj=new Object();只要强引用还存在,垃圾回收器永远不会回收被引用的对象

软引用:软引用用来描述一些还有用但是并非必须的对象,对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收单位之中进行第二次回收,如果这次回收之后还没有足够内存,才会抛出异常

弱引用:弱引用用来描述非必需对象,他的强度比软引用更弱,被弱引用关联的对象只能生存到下次垃圾收集之前,当垃圾收集器工作时,无论内存是否足够,都会回收掉只被弱引用关联的对象

虚引用:虚引用又称幽灵引用或者幻影引用,它是最弱的一种引用关系,一个对象是否有虚引用,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例,为一个对象设置虚引用关联的唯一目的就是能够在这个对象被垃圾回收器回收时收到一个系统通知;

垃圾收集算法:
垃圾收集算法一共有四种,分别是标记清除算法,复制算法,标记整理算法,分代收集算法(新生代采用复制算法,老年代采用标记整理或标记清除算法)。

内存回收策略:
对象有现在Eden区分配。
大对象直接进入老年代(默认年龄15岁)。
长期存活的对象将进入老年代(默认年龄15岁)。
动态对象年龄判定(在Survovor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代)。
空间分配担保(在发生Minor GC之前,虚拟机会检查老年代最大可用连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC是安全的,否则的话就看是否允许担保失败,如果允许,就看老年代最大连续可用空间是否大于历次晋升老年代对象的平均大小,如果大于就可以尝试进行Minor GC)。
虚拟机的性能监控工具:
jps:虚拟机进程状况工具
jstat:虚拟机统计信息监视工具
jinfo:java配置信息工具
jmap:java内存映像工具
jhat:虚拟机堆转储快照分析工具
jstack:虚拟机堆栈跟踪工具

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值