JVM调优专题-JVM内存原理及内存结构

作为JAVA开发工程师,相信大家对JVM并不陌生,作为Java程序基础编译和执行平台,自然占据着相当重要的地位。Java语言的跨平台性和垃圾回收机制,简直是程序员的福音,一次性充分的解决了最让人头疼的兼容性问题和内存问题,真是个天才的设计^v^。所以啊,我们日常工作中无需过多的关注JVM的问题,这就导致了即使对jvm不熟悉也不影响我们的软件运行,其实这里有利也有弊,这样可能会存在一些隐藏的问题不能被发现,会在某些情况下集中爆发,不利于顺利实施一个成熟可靠地软件产品。所以在某些情况下,JVM调优就显得尤为重要。

笔者在面试初级、中级工程师时,很少会问到JVM调优的相关问题,因为这些问题他们可能确实没遇到过,或者我们压根并不指望初、中级工程师能完美解决类似问题。在面试高级程序员时,这类问题就是必问的了,有过类似的经验才能从中汲取更多的经验,以至于能将产品做的尽善尽美。

本专题预计会从以下方面对JVM展开讨论,依次在后续章节中讨论,基本涵盖了面试常见问题以及工作中所能遇到的JVM问题:

  • JVM原理及内存结构
  • JVM调优参数
  • 内存溢出原因及解决方案
  • 垃圾回收机制
  • JVM调试工具

首先我们先来了解下什么是Java、什么是JVM、以及一些必要的执行原理,这样才能更好的理解Java这门语言,从而在一起深入探讨JVM。

对Java平台的理解

Java平台特征

Java本身是一种面向对象的语言,且简单易用、功能强大。相比较于其他编程语言,最显著的两个基本特征是:

  • 书写一次,到处运行(Write once, run anywhere),充分的体现了java语言的跨平台性
  • 垃圾收集(Garbage Collector),java通过垃圾收集器来回收和分配内存,大部分情况下,程序猿不需要自己操心内存的分配和回收。

JVM、JRE、JDK的关系

对于Java通常有以下概念需要我们理解:

  • JVM(Java Virtual Machine),java虚拟机,解释运行Java字节码的标准和规范
  • JRE(Java Runtime Environment),java运行时环境,包含JVM和java类库,以及一些模块等。
  • JDK(Java Development Kit),java开发工具包,包含JRE以及更多的工具,比如编译器、各种诊断工具等

所以这三者关系应该是:JDK > JRE > JVM。

Java是解释执行的吗

对于“Java 是解释执行”这句话,这个说法不太准确。我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode),然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行的。

JVM原理

JVM中文名是Java虚拟机,可理解为是一个虚拟机器,来模拟通用的物理机。JVM是一个标准,一套规范,  规定了.class文件在其内部运行的相关标准和规范。及其相关的内部构成。 比如:所有的JVM都是基于栈结构的运行方式。

JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。

Java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令解释成不同平台机器码,通过特定平台运行。

 

Java内存区域划分

Java程序在运行时需要一定的内存空间,这些内存空间存储着Java程序所需的数据,根据数据存储类型和功能划分,Java内存结构可用下图表示:

类加载子系统

负责从文件系统或者网络加载Class信息,加载的信息存放在一块称之方法区的内存空间。

方法区

存放类的信息、常量信息、常量池信息、包括字符串字面量和数字常量等。

Java堆

在Java虚拟机启动的时候建立Java堆,它是Java程序最主要的内存工作区域,几乎所有的对象实例都存放到Java堆中,堆空间是所有线程共享。堆也是垃圾收集器重点照顾的区域,所以堆内空间还会被不同的垃圾收集器进行进一步的细分,最有名的就是新生代、老年代的划分。

根据垃圾回收机制的不同,Java堆有可能拥有不同的结构,最为常见的就是将整个Java堆分为新生代和老年代。其中新声带存放新生的对象或者年龄不大的对象,老年代则存放老年对象。新生代分为Eden区、s0区、s1区,s0和s1也被称为from和to区域,他们是两块大小相等并且可以互相角色的空间。绝大多数情况下,对象首先分配在eden区,在新生代回收后,如果对象还存活,则进入s0或s1区,之后每经过一次新生代回收,如果对象存活则它的年龄就加1,对象达到一定的年龄后,则进入老年代。

​​​​​​​直接内存

JavaNio库允许Java程序访问直接内存,从而提高性能,通常直接内存速度会优于Java堆。读写频繁的场合可能会考虑使用。

​​​​​​​虚拟机栈

一个线程的Java栈在线程创建的时候被创建,Java栈保存着局部变量、方法参数、同时Java的方法调用、返回值等。

​​​​​​​本地方法栈

最大不同为本地方法栈用于本地方法调用。Java虚拟机允许Java直接调用本地方法(通过使用C语言写)

​​​​​​​垃圾收集器(Garbage Collector)

GC机制是Java的核心,也是不可少的,Java有一套自己进行垃圾清理的机制,开发人员无需手工清理。

​​​​​​​程序计数器(Program Counter)

也称为PC寄存器,每个线程私有的空间,Java虚拟机会为每个线程创建PC寄存器,在任意时刻,一个Java线程总是在执行一个方法,这个方法称为当前方法,如果当前方法不是本地方法,PC寄存器总会执行当前正在被执行的指令,如果是本地方法,则PC寄存器值为Underfined,寄存器存放当前执行环境指针、程序计数器、操作栈指针、计算的变量指针等信息。

​​​​​​​执行引擎

虚拟机核心的组件。它负责执行虚拟机的字节码,一般会先进行解释成机器码后执行。

https://static001.geekbang.org/resource/image/36/bc/360b8f453e016cb641208a6a8fb589bc.png

 

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页