签名:但行好事,莫问前程。
文章目录
前言
JVM是每个程序员绕不过去的一个坎,既然绕不过去,那便试着跨过它。
一、什么是JVM?
定义:Java虚拟机(Java Virtual Machine 简称JVM)是Java程序(Java二进制字节码)的运行坏境。
二、JVM的优点:
1、一次编写,导出运行
Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
2、自动内存管理,垃圾回收功能(重点)
三、JVM、JRE、JDK之间的关系
- JVM:Java虚拟机,是运行所有Java程序的抽象计算机,是Java语言的运行环境。
- JRE(Java Runtime Environment):Java运行时环境,包含了一个JVM(Java虚拟机),与Java核心类库与其所支持的文件。
- JDK (Java Development Kit):Java开发工具包,包括了Java运行环境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。
四、JVM的内存结构
JVM分为五个区域:程序计数器、虚拟机栈、本地方法栈、堆、方法区。
1、程序计数器
程序计数器(Program Counter Register):程序计数器的作用可以看做是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变计数器的值来选取下一条字节码指令。其中,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器来完成。(总结:记录下一条JVM指令的执行地址)
特点:
- 线程私有
- 不会内存溢出(规定)
2、虚拟机栈
虚拟机栈(JVM Stacks):每个线程运行时所需要的内存,称为虚拟机栈。每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存。每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。(总结:每个线程运行时所需要的内存称之为虚拟机栈)
栈帧(Frame):每个方法运行时需要的内存。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用至执行完成的过程,都对应着一个栈帧在虚拟机栈里从入栈到出栈的过程。
特点:
- 先进后出,后进先出
- 栈内存不需要进行垃圾回收(方法调用完成就会释放栈内存)
- 方法内的局部变量线程安全
栈内存溢出:java.lang.StackOverflowError
-
栈帧过多导致栈内存溢出(比如,递归调用)
-
栈帧过大导致栈内存溢出
3、本地方法栈
本地方法栈(Native Method Stacks):本地方法栈与虚拟机栈作用相似,区别在于虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈是为虚拟机使用到的Native(本地)方法服务。
本地方法:通过native接口去调用c/c++的底层实现。例如:Object的clone()就是本地方法。
4、堆
堆(Heap):通过new关键字创建的对象都会只用堆内存。
特点:
- 堆是线程共享的,堆中的对象都需要考虑线程安全问题。
- 有垃圾回收机制,堆中不再被引用的对象就会被垃圾回收。
堆内存溢出:java.lang.OutofMemoryError
- java.lang.OutofMemoryError:java heap space 发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之前,虚拟机分配的到堆内存空间已经用满了,与Heapspace有关。
5、方法区
方法区(Method Area):方法区是Java虚拟机所有线程共享区,它存储的是已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。(总结:方法区存储的就是跟类相关的信息。)
方法区的实现
JVM内存结构 1.6 的方法区:PermGen space 永久代(实现)
JVM内存结构 1.8 的方法区:Metaspace 元空间(实现)
方法区内存溢出
元空间(1.8)内存不足导致的内存溢出:
永久代(1.6)空间不足导致的内存溢出:
总结
博客主要记录了JVM的一些基本概念,先混个眼熟,后续加深对JVM的学习,如果对你有帮助,请一键三连。
鸣谢:黑马程序员的JVM教程:JVM学习视频地址