JVM1_初识JVM、JVM内存结构、程序计数器、虚拟机栈、本地方法栈、堆、方法区、StringTable字符串常量池垃圾回收、优化

引言

随着Java行业竞争越来越激烈,面试的难度也在不断的提升

初级程序员也是很有必要了解掌握JVM,简单说是为了应对面试,换句话说也是为了长远

学习JVM可以更好的理解一些底层的实现

  • 自动拆箱、装箱
  • foreach怎么实现的
  • 动态代理相关

目录

  • 1JVM简单介绍
  • 2JVM学习路线
  • 3内存结构
    • 3.1程序计数器
    • 3.2虚拟机栈
    • 3.3本地方法栈
    • 3.4堆
    • 3.5方法区
  • 4StringTable字符串常量池

开始

1简单介绍

在这里插入图片描述
在这里插入图片描述

2学习路线
  • JVM内存结构
  • GC垃圾回收
  • 字节码
  • 类加载器
  • 解释器、即时编译器

在这里插入图片描述

3JVM内存结构
3.1程序计数器(物理实现为寄存器)

在这里插入图片描述

作用:

Program Counter Register 记录下一条jvm指令的执行地址

原理:

Java源代码经编译之后,变成二进制字节码(对应为jvm指令),然后jvm将指令 经过 解释器解释为 机器码,最后CPU执行

特点:

  • 线程私有:各个线程在时间片结束的时候,每个线程都有一个私有的程序计数器 记录当前线程的 执行位置
  • 不会存在内存溢出
3.2虚拟机栈
  • 栈-线程运行需要的内存空间(每个线程都会对应一个虚拟机栈)

  • 栈帧-一个栈可以看做是多个栈帧组成,一个栈帧对应着一次方法的调用(每个方法运行时需要划分一个栈帧内存,形参、局部变量、返回地址,栈帧的大小由上述三者决定)

  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

定义

Java Virtual Machine Stacks

演示栈帧

在这里插入图片描述

问题辨析

  • 垃圾回收是否涉及栈内存—》不涉及,方法结束会自动弹栈
  • 栈内存分配越大越好吗—》不是,栈内存越大,线程数越少,因为每个线程都有一个虚拟机栈。可以通过虚拟机参数来指定 -Xss yoursize,Windows下根据虚拟内存来给定,其他操作系统下为1024kb
  • 方法内的局部变量是否线程安全—》安全,变量是私有的。每个线程的虚拟机栈是私有的
    • 判断一个变量是不是线程安全的,不仅需要判断是不是方法内的局部变量,还需要判断 是否逃离方法的作用范围(形参、return,即是否别的线程能拿到该变量)
3.3栈内存溢出

原因

  • 栈帧过多:栈帧(每一次方法的调用)过多,栈空间不足,如无终结递归
  • 栈帧过大

案例一:找出CPU占用过多的代码

  • top:查看JVM虚拟机下的所有进程,找对对应线程的编号
  • ps H -eo pid,tid,%cpu | grep 待查进程id:查看进程和该进程对应的多个线程,找出哪个线程占用的CPU过高
  • jstack 进程id :查看当前进程对应的全部线程的详细信息(需要注意将10进制转化为16进制进行比对查看),找出对应的代码位置

案例二:程序运行很长时间没有结果(可能多个线程发生死锁)

  • jstack 进程id:查看两线程之间是否发生死锁,找出对应代码的位置

在这里插入图片描述

3.4本地方法栈

在这里插入图片描述
在JVM调用本地方法的时候,会自动开辟的空间栈,Native Method Stacks

  • 本地方法:由其他语言像c、c++编写的操作系统底层打交道的方法,像Object类的clone()方法,就是本地方法
3.5堆

Heap,前面的栈都是线程私有的,堆是线程共享的

  • 通过new关键字,创建对象都会使用堆内存
  • 它是线程共享的,堆中对象都要考虑线程安全问题
  • 有垃圾回收机制

堆内存溢出问题

在这里插入图片描述
在这里插入图片描述

  • 虽然有垃圾回收机制,但是对象在使用中不被回收累计的情况下,也是会发生堆内存溢出的问题

堆内存诊断

  1. jps工具:查看当前系统中有哪些java进程
  2. jmap工具:查看堆内存的占用情况,只能看某一时刻的
  3. jconsole工具:图形化界面的,多功能的监测工具,可以连续监测,线程、cpu等

直接在控制台输入工具代码即可使用
在这里插入图片描述
在这里插入图片描述

案例:垃圾回收后,程序仍然占用很高的内存

  • jvisualvm工具:可视化虚拟机工具

在这里插入图片描述

3.6方法区

方法区特点

  • 所有JVM线程共享的区域(类似堆是线程共享的)
  • 存储跟类结构相关的一些信息,像运行时常量池
    • 像类的成员变量、成员方法、构造器方法的代码
    • 方法数据、特殊方法(类的构造器)
  • 方法区在JVM虚拟机启动的时候创建
  • 方法区逻辑上是堆得概念(可以被看做JVM假的堆),但是JVM厂商在实现的时候不一定,
    • 在JVM堆内物理实现—》JDK1.8之前,永久代 PermGen space
    • 在操作系统也就是JVM之外物理实现—》JDK1.8之后,元空间 Metaspace
  • 内存也是会溢出的

在这里插入图片描述

方法区内存溢出的现象

在这里插入图片描述

运行时常量池

  • 二进制字节码.Class(包括类基本信息、常量池、类方法定义、虚拟机指令)
  • 可以通过 javap -v 字节码文件 反编译为我们能读懂的信息,JVM主要根据 #数字 去常量池中找一些静态变量等的相关信息
  • 常量池:就是一张表存在.class字节码文件中,给JVM指令提供一些常量符号,便于查找,要执行的类名、方法名、参数类型、字面量等
  • 运行时常量池:常量池是.class文件中的,当该类被加载时,他的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实的地址(就是放进运行时真实的内存,将真实地址对应起来)

在这里插入图片描述

在这里插入图片描述

3.7StringTable字符串常量池

往期博客相关:

Java课堂篇3_对象类型下的“==“和equals()、字符串常量池、(-128-127)int类型装箱Integer大整型常量池、关于static关键字

Java课堂篇9_String、StringBuilder、StringBuffer简单理解

字符串常量池StringTable 和 常量池、运行时常量池的联系

  • StringTable的数据结构为HashTable结构,JVM刚启动的时候为空状态
  • JVM启动之后,方法区常量池的信息,都会被加载到运行时常量池中,这时 代码中的String str = "a"中的a还是常量池中的符号,还没变成java对象
  • JVM执行完 方法区中的JVM创建该变量的虚拟机指令后,会把 符号a 变为 字符串对象a,然后去找StringTable中是否存在 对象a
    • 不存在:直接将字符串对象 a对象 放入字符串常量池
    • 存在:直接指向字符串常量池中的对象

举栗1

String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = s1 + s2; //----> new StringBuilder().append("a").append("b").toString()

//而StringBuilder的toString() 方法----》new String("ab");

在这里插入图片描述

举栗2

String s3 = "ab";
String s5 = "a" + "b";

// s3 和 s5 引用的为一个字符串常量池中的对象 "ab"

原理是javac在编译器的优化,结果已经在编译器间确定 "a" + "b"为 "ab"

StringTable字符串常量池的特性

  • 常量池中的字符串仅仅是符号,第一次用到才变为对象
  • 利用串池的机制,来会面重复创建字符串对象
  • 字符串变量拼接的原理是StringBuilder(1.8)
  • 字符串常量拼接的原理是编译器优化
  • 可以使用intern方法,主动将串池中还没有的字符串对象放入串池

JDK1.8之后,直接入池,本身直接从堆指向池子

在这里插入图片描述

对比 (注意这是1.8之后的环境)
在这里插入图片描述
在这里插入图片描述

JDK1.8之前,intern()方法会创建一个 副本 入池,本身还是指向堆区,

在这里插入图片描述
对比

在这里插入图片描述
面试题
在这里插入图片描述

3.8StringTable的位置

JDK1.6的时候,StringTable字符串常量池在 永久代方法区的常量池中,但是大量的字符串常量会导致永久代的内存不足

JDK1.7及以后,StringTable字符串常量池 挪到了堆中,便于垃圾回收

在这里插入图片描述

3.9StringTable的垃圾回收机制

当内存空间不足的时候,字符串常量池中的常量也会被垃圾回收

3.10StringTable的性能调优

数据结构为hash表,数组挂链表

  • 当hash桶的个数较多时,冲突少,查找速度较快
  • 当hash桶的个数较少时,冲突多,查找速度较慢

在这里插入图片描述

现实场景:可以将内存中的字符串对象考虑是否入池,如果内存中有大量的重复的字符串对象,可以入池减轻内部的压力

猜你喜欢

转载自blog.csdn.net/qq_24654501/article/details/112592430
今日推荐