1.JVM的内存模型(1.8)
程序计数器: 它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
本地方法栈:存放的是值类型(int、float等)的值和引用类型(String、你自己创建的类对象等)在堆中的地址;堆中存放引用类u型的值,如果堆中某个值的地址在栈中没有被指向,他就会被GC回收。
java虚拟机栈:它的作用就是 主要管Java程序的运行,它保存方法的局部变量表、部分结果、并参与方法的调用和返回。 它的生命周期是和线程一样的。
堆:就是存放对象的实例
本地内存区:
元数据区:在java8之前是方法区 ,元数据区是在java8后替代了方法区,元数据区也是一块可以共享的内存区,里面主要用来保存被虚拟机加载的类信息,常量,静态变量和编译器编译后的代码等数据。
直接内存:直接内存无需进行与java堆内存进行映射和转换,可以直接去操作系统内存。
优点:会减少GC回收,提高IO速度
缺点:直接内存没有JVM协助管理内存,需要我们自己收到来管理堆外的内存,防止内存溢出同时也为了避免一直有FULLGC最终会导致物理内存被消耗完。
2.Java类加载过程
加载,连接 (验证,准备,解析),初始化,使用,卸载。
加载:加载主要是将.class文件(也可以是zip包)通过二进制字节流读入到JVM中。 在加载阶段,JVM需要完成3件事: 1)通过classloader在classpath中获取XXX.class文件,将其以二进制流的形式读入内存。 2)将字节流所代表的静态存储结构转化为方法区的运行时数据结构; 3)在内存中生成一个该类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
3.双亲委派模型
子类加载器先让父类加载器去查找该类来加载,父类又继续请求它的父类直到最顶层,在父类加载器没有找到所请求的类的情况下,子类加载器才会尝试去加载,这样一层一层上去又下来
4. 如何打破双亲委派机制
打破双亲委派机制不仅要继承ClassLoader类,还要重写loadClass和findClass方法
5.内存泄漏和内存溢出
内存泄漏(memoryleak),是指应用程序在申请内存后,无法释放已经申请的内存空间,一 次内存泄漏危害可以忽略,但如果任其发展最终会导致内存溢出(outofmemory)。如读取文件后流要进行及时的关闭以及对数据库连接的释放。
内存溢出(outofmemory)是指应用程序在申请内存时,没有足够的内存空间供其使用。如我们在项目中对于大批量数据的导入,采用分批量提交的方式。
6. JVM性能的调优
1. 设定堆内存大小
2. 设定新生代大小。新生代不宜太小,否则会有大量对象涌入老年代
-XX:NewSize:新生代大小
-XX:NewRatio:新生代和老年代占比
-XX:SurvivorRatio:伊园
3、设定垃圾回收
年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC
7. JVM调优命令
Sun JDK 监控和故障处理命令有jps jstat jmap jhat jstack jinfo
1、jps,JVM Process Status Tool,显示指定系统内所有的HotSpot 虚拟机进程。
2、jstat,JVM statistics Monitoring 是用于监视虚拟机运行时状态信息的命令,它可以显 示出虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据。
3、jmap,JVM Memory Map 命令用于生成heap dump 文件
4、jhat,JVM Heap Analysis Tool 命令是与jmap 搭配使用,用来分析jmap 生成的 dump, jhat
内置了一个微型的HTTP/HTML 服务器,生成dump 的分析结果后,可以在浏览器中查看
5、jstack,用于生成java 虚拟机当前时刻的线程快照。
6、jinfo,JVM Configuration info 这个命令作用是实时查看和调整虚拟机运行参数。