• JDK:java 开发工具:包含javac、javap命令及JRE
  • JRE:java运行环境:包含java常用的util、集合包和VM

JDK、JRE、VM、java虚拟机调优

  • 一次编译,到处运行:比如下面Hellowworld.java文件通过javac命令编译成class文件,再通过java命令放到JVM虚拟机上运行,然后转化成不同系统的机器码运行(所以再Oricle官网下载JDK时需要选择不同的操作系统,他会屏蔽不同操作系统在底层硬件与指令上的区别),windows机器码为0101结构

JDK、JRE、VM、java虚拟机调优

  • JVM虚拟机由类装载子系统、运行时数据区、字节码执行引擎三部分组成。class文件通过java命令由类装载子系统加载到内存区域、由执行引擎来执行class文件。

JDK、JRE、VM、java虚拟机调优

  • 命令使用:以IDEA开发工具,ArrayDemo.java类为例
  • 找到类右击,选择Open in Terminal
    JDK、JRE、VM、java虚拟机调优
    输入命令javac 类名.java(将java文件编译成class文件)
    JDK、JRE、VM、java虚拟机调优
    输入命令javap -c 类名.class(对代码进行反汇编,将16进制看不懂的class文件(官网可以查到16进制class文件对应的意思)汇编成可读的字节码
    JDK、JRE、VM、java虚拟机调优
    可以再通过命令javap -c 类名.class >类名.txt(导出txt文件来分析)
    JDK、JRE、VM、java虚拟机调优
    code字节码意思可以区去Orical官方JVM指令手册去查找对应意思,其实也就那几个,不难
    例子:
    JDK、JRE、VM、java虚拟机调优
    JDK、JRE、VM、java虚拟机调优

JDK、JRE、VM、java虚拟机调优

  • 对象都在堆中,其它区存放的都是对象的引用

  • 栈:每个线程分别为一个栈帧,先进后出

  • 局部变量表:存放局部变量,如果该局部变量是new出来的(比如main方法中创建一个对象),则该局部变量为一个指针,指向堆里该对象的位置

  • 操作数栈:存放临时操作数的内存区域

  • 方法出口:存放调用该方法的位置

  • 程序计数器:存放当前线程执行代码的位置,由执行引擎对其修改。一条线程分配一块程序计数器内存

  • 方法区:存放常量、静态变量、类信息(由类装载子系统装载进来的class文件,由字节码执行引擎执行该class文件)

  • 本地方法栈:运行本地方法时,需要用到的一块存放区域(比如:new Thread()时,会调用start方法,而start会调用start0方法,该方法就是用native修饰的本地方法,该方法用C语言写的)

  • 堆:
    JDK、JRE、VM、java虚拟机调优

  • Minor GC
    JDK、JRE、VM、java虚拟机调优

  • 执行第一次Minor GC后,将非垃圾对象放到Survivor的From区同时这些对象的分代年龄+1(分代年龄保存在对象头里),然后对Eden区剩余的对象进行清除。第二次Minor GC的区域是Eden区和Survivor的From区,将非垃圾对象放到Survivor的To区同时分代年龄+1,然后对Eden区和From区进行垃圾清除。第三次Minor GC的区域是Eden区和Survivor的To区,将非垃圾对象放到Survivor的From区同时分代年龄+1,然后对Eden区和To区进行垃圾清除,然后Minor GC就是在第二次、第三次这样反复执行。当分代年龄达到15时,会被移到老年代区域(注意:分代年龄是可以设置的),被挪到老年代一般是静态变量的对象、线程池的对象、Spring容器的bean对象,随着程序的运行会一直存活在老年代。当老年代放满后,会执行full GC(对所有内存进行垃圾回收),执行full GC时会STW停掉用户的应用线程,出现卡顿现象(Minor GC也会STW,但时间非常端,用户几乎无感知)。当老年代满了,回收不了了会OOM,就是内存溢出

JDK、JRE、VM、java虚拟机调优
通过JDK自带的命令工具jvisualvm查看本机当前java进程
JDK、JRE、VM、java虚拟机调优
然后自动打开以下界面,通过此工具诊断java虚拟机内部运行情况
JDK、JRE、VM、java虚拟机调优
可以看到具体每块区域的运行情况
JDK、JRE、VM、java虚拟机调优

  • java虚拟机调优目的:减少STW

  • Java中Stop-The-World机制简称STW,是在执行垃圾收集算法时,java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外)。Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互;这些现象多半是由于gc引起。

  • java调优:根据核心业务占用内存进行预估,再预设置,然后再调优。例子:
    假定每秒1000单,分三台4核8G的服务器跑(一般情况分配3-4G给操作系统,所以最多虚拟机内存只能给4-5G),平均每台300单/秒
    假如刚开始取值大小如下
    JDK、JRE、VM、java虚拟机调优
    JDK、JRE、VM、java虚拟机调优
    JDK、JRE、VM、java虚拟机调优
    JDK、JRE、VM、java虚拟机调优

  • 每个线程设置为1M,300单/每秒(不包括订单查询等操作),因此就是300M/秒

  • 比如分三个G给堆,按照堆正常老年代2/3,年轻代按8:1:1划分,数据如上。这eden区13秒就会满,假如每个订单1秒就完成,则在13秒时执行minor GC会有60M为非垃圾对象进入s区。此时在S区根据对象动态年龄判断,如果一批对象总大小超过S0/S1区50%,就直接进入老年代(可通过-XX:TargetSurvivorRatio设置),这样计算老年代将6分钟左右就满了,执行full GC后又基本清空。因此就可以在S区进行扩大,而扩大后仍然按照8:1:1的内存分配。这是如果给年轻代配2G,老年代1G,则结果如图
    JDK、JRE、VM、java虚拟机调优
    JDK、JRE、VM、java虚拟机调优
    这样eden区大概25秒执行一次minor GC, S区也不会一次性超过一半。

JDK、JRE、VM、java虚拟机调优

相关文章:

  • 2021-10-03
  • 2021-07-07
  • 2021-05-26
  • 2021-07-30
  • 2021-07-13
  • 2022-01-30
  • 2021-11-27
  • 2022-01-15
猜你喜欢
  • 2021-07-30
  • 2021-10-26
  • 2021-08-01
  • 2022-12-23
  • 2022-01-14
  • 2021-11-23
  • 2021-11-18
相关资源
相似解决方案