JVM的原理

jvm分区

Heap (堆区):主要存储new出来的对象实例,Java堆中细分为新生代老年代一个新生代分为1个Eden区2个Survivor区,说明:绝大部分对象在Eden区生成,当Eden区装填满的时候,会触发Young Garbage Collection,即YGC。垃圾回收的时候,在Eden区实现清除策略,没有被引用的对象则直接回收。依然存活的对象会被移送到Survivor区。Survivor区分为so和s1两块内存空间。每次YGC的时候,它们将存活的对象复制到未使用的那块空间,然后将当前正在使用的空间完全清除,交换两块空间的使用状态。如果YGC要移送的对象大于Survivor区容量的上限,则直接移交给老年代

元空间区:jdk1.7的方法区移到了元空间,比如类元信息、字段、静态属性、方法、常量等都移动到元空间区元空间并不在虚拟机中,而是使用本地内存

栈:栈里面存的都是一些局部变量,比如8大基本数量类型,还有线程运行,方法运行都在栈里面,另外创建对象的时候的引用也是存在栈里面的

程序计数器是一块较小的内存空间。是线程私有的。它可以看作是当前线程所执行的字节码的行号指示器

类加载

类加载器有这几个:

启动类加载器:jvm启动的时候,会优先加载<JAVA_HOME>\lib这个目录的核心类库。

扩展类加载器:负责加载<JAVA_HOME>\lib\ext这个目录的类。

应用程序类加载器:负责加载我们写的代码。

自定义类加载器:根据我们的需要,加载特定的类。

下图展示了类加载器直接的层次关系,成为类加载器的双亲委派模型。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。

它的工作过程是这样的:

  1. 应用程序类加载器收到了类的加载请求,先问扩展类加载器是否可以加载。
  2. 扩展类加载器也不会直接去加载,他也是向上级启动类加载器询问是否可以加载。
  3. 启动类加载器在自己负责的目录搜索了一下,发现自己找不到这个类,就说不行,你自己加载吧。
  4. 扩展类加载器在自己负责的目录搜索了一下,发现自己找不到这个类,就说不行,你自己加载吧。
  5. 应用程序类加载器在自己负责的目录搜索了一下,找到了这个类,把Hello类加载进来。

双亲委派模型一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。

双亲委派存在得意义是什么?

保证系统的安全

垃圾回收器有哪些?

串行垃圾回收器(Serial):它为单线程环境设计并且只使用一个线程进行垃圾回收,会暂停所有的用户线程。所以不适合服务器环境。

并行垃圾回收器(Parallel):多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景。jdk8默认的是使用的Parallel并行回收器

并发垃圾回收器(CMS):用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程。互联网公司多用它,适用于对响应时间有要求的场景。

垃圾回收算法?

标记清除

复制算法:

标记整理:

分代收集算法:

JVM调优的几种场景

CPU占用过高

CPU过高的原因一般是,死循环递归计算量大线程数过多,怎么确定CPU飙升的问题如下:

top命令查看cpu占用情况

top -Hp命令查看线程的情况

可以看到是线程id为7287这个线程一直在占用cpu,把线程号转换为16进制用jstack工具查看线程栈情况

内存溢出解决

程序发生内存泄漏后,进程的可用内存会慢慢变少,最后的结果就是抛出OOM错误。发生OOM错误后可能会想到是内存不够大,于是把-Xmx参数调大,然后重启应用。这么做的结果就是,过了一段时间后,OOM依然会出现。最后无法再调大最大堆内存了,结果就是只能每隔一段时间重启一下应用

用jstat分析gc活动情况

jstat是一个统计java进程内存使用情况和gc活动的工具,参数可以有很多,可以通过jstat -help查看所有参数以及含义

用jmap工具dump出内存快照

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值