首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JVM (Hot Sport 版)

JVM (Hot Sport 版)

作者头像
收心
发布2022-01-14 10:10:50
发布2022-01-14 10:10:50
29300
代码可运行
举报
文章被收录于专栏:Java实战博客Java实战博客
运行总次数:0
代码可运行

JVM 是 Java 程序员中高级开发的必备技能之一,也是未来长久发展的核心!!!~

什么是JVM?

JVM 是Java虚拟机。他它是实现Java代码,一处编写,处处运行的基础。也是Java二进制代码的运行环境

JVM优势:

  • 提供了自动的内存管理机制:垃圾回收机制!
  • 一处编写,处处运行的基础
  • 数组下标越界的检查

内存泄漏

说明:内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

JVM、JRE、JDK 关系

JVM 是一套规范,很多公司 都实现过JVM 我们常用的就是Open JDK、Oracle JDK,不同规范应用范围不同,同时受到的限制也不同!我们常用就是 OpenJDK

JVM 结构

图1

图2

按顺序学习 由浅入深的学习 顺序是: JVM 内存结构 、 垃圾回收 、 Java Class编译优化 、 类加载器

JVM的内存划分

顺序:

  • 程序计数器
  • 虚拟机栈

程序计数器 Program Counter Register

  • 作用:是记录下一条 JVM 指令的执行地址行号。(由物理的寄存器实现的)

特点:

  • 是线程私有的(属于自己的线程的)
  • 不会存在内存溢出
  • 每个线程,都有自己的程序计数器

内存溢:Out of Memory 是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。

下面是一个.class字节码信息

代码语言:javascript
代码运行次数:0
运行
复制
A : B                   C       // D
0 : getstatic 		#20	// PrintStream out = System.out; 
3 : astore_1			// -- 
4 : aload_1 			// out.println(1); 
5 : iconst_1 		  	// -- 
6 : invokevirtual 	#26  	// -- 
9 : aload_1 			// out.println(2); 
10: iconst_2          		// -- 
11: invokevirtual 	#26 	// -- 
14: aload_1 		  	// out.println(3); 
15: iconst_3          		// -- 
16: invokevirtual 	#26 	// -- 
19: aload_1           		// out.println(4); 
20: iconst_4          		// -- 
21: invokevirtual 	#26 	// -- 
24: aload_1           		// out.println(5); 
25: iconst_5          		// -- 
26: invokevirtual 	#26 	// -- 
29: return

说明 每一列是一串二进制字节码 由 A B C D 四部分组成

A 列:就是 程序计数器 记录的数字

虚拟机栈 (栈帧:先进后出)

  • 每个线程运行需要的内存空间,称为虚拟机栈
  • 每个栈由多个栈帧(Frame)组成,对应着每次调用方法时所占用的内存
  • 每个线程只能有一个活动栈帧(顶部的栈帧就是活动栈帧 如下图 栈帧4 就是活动栈帧),对应着当前正在执行的方法

栈帧包含的内容:

栈问题辨析:

1)垃圾回收是否涉及栈内存?

  • 不会。栈内存是方法调用产生的,方法调用结束后会弹出栈。

2)栈内存分配越大越好吗?(就是启动命令加上参数 -Xss就是设置的栈大小)例如 -Xss1m、-Xss1024k 、-Xss1048576

  • 不一定。因为计算机物理内存是一定的,线程占用物理内存的 ,线程中栈内存越大,虽然可以支持更多的递归调用,但是受到物理限制,(可执行的)线程数就会越少。 比如物理内存200M 每个栈占用 5M 那么最多创建40个线程执行。栈小一点 就可以创建更多的线程!

3)方法呢的局部变量是否线程安全

  • 如果方法内部的变量没有逃离方法的作用访问,它是线程安全的
  • 如果是局部变量引用了对象,并逃离了方法的访问,那就要考虑线程安全问题。

总结一句:栈帧内部自己的内存不用别人的,也不让别人用。就是线程安全的

4)栈内存溢出 (推荐使用 -Xss256k 指定栈内存大小!)

递归调用导致栈帧过多,栈帧过大、或者第三方类库操作,都有可能造成栈内存溢出 java.lang.stackOverflowError ,推荐使用 -Xss256k 指定栈内存大小!

线程运行诊断

案例一:代码运行 CPU 占用过多 解决方法:Linux 环境下运行某些程序的时候,可能导致 CPU 的占用过高,这时需要定位占用 CPU 过高的线程

步骤:

用top命令得到进程(process ID)pid,再用ps命令得到进程pid中有问题的线程(thread ID)tid 最后用jstack 拿到tid 转为16进制 对比 nid

  1. top 命令,查看是哪个进程占用 CPU 过高
  2. ps H -eo pid, tid(线程id), %cpu | grep :刚才通过 top 查到的进程号 通过 ps 命令进一步查看是哪个线程占用 CPU 过高 得到tid
  3. jstack 线程 id :通过对比线程的 tid ,定位出错代码的行数,通过 ps 命令看到的 nid 来对比定位,注意 jstack 查找出的线程 id 是 16 进制的,需要我们拿到pid 转换为16禁止 对比 nid。

本地方法栈

一些带有 native 的关键字修饰方法就是。需要 JAVA 去调用本地的C或者C++方法,因为 JAVA 有时候没法直接和操作系统底层交互,所以需要用到本地方法栈,服务于带 native 关键字的方法。

此图就是Object 的 clone方法 他是native修饰的 说明实现是有底层调用本地C 或者C++来实现的

堆 Heap

  • 通过new关键字创建的对象都会被放在堆内存

特点

  • 它是线程共享,堆内存中的对象都需要考虑线程安全问题
  • 有垃圾回收机制

2)堆内存溢出

java.lang.OutofMemoryError :Java heap space. 堆内存溢出 可以使用 -Xmx8m 来指定堆内存大小

堆内存诊断分析

代码

代码语言:javascript
代码运行次数:0
运行
复制
public class Jvm {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("in 1");
        Thread.sleep(30000);


        byte[] bytes = new byte[1024 * 1024 * 10];
        System.out.println("in 2");
        Thread.sleep(30000);

        bytes = null;
        System.gc();
        System.out.println("in 3");
        Thread.sleep(1000000l);

    }
}

方式一:

1、查看当前系统中有哪些 java 进程

代码语言:javascript
代码运行次数:0
运行
复制
jps

当然知道我们Java项目的运行端口也可以 lsof -i:端口

2、查看堆内存占用情况 jmap – heap 进程id

代码语言:javascript
代码运行次数:0
运行
复制
jmap -heap 进程id
代码语言:javascript
代码运行次数:0
运行
复制
[root@iZuf6XXXXXXXvkjjn20Z ~]# lsof -i:18081
COMMAND   PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
java    10140 root  166u  IPv6 308674937      0t0  TCP *:18081 (LISTEN)


[root@iZuf6XXXXXXXvkjjn20Z ~]# jmap -heap 10140
Attaching to process ID 10140, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.121-b13

using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 536870912 (512.0MB)
   NewSize                  = 268435456 (256.0MB)
   MaxNewSize               = 268435456 (256.0MB)
   OldSize                  = 268435456 (256.0MB)
   NewRatio                 = 1
   SurvivorRatio            = 30
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 251658240 (240.0MB)
   used     = 207160352 (197.56350708007812MB)
   free     = 44497888 (42.436492919921875MB)
   82.31812795003255% used
From Space:
   capacity = 8388608 (8.0MB)
   used     = 2884576 (2.750946044921875MB)
   free     = 5504032 (5.249053955078125MB)
   34.38682556152344% used
To Space:
   capacity = 8388608 (8.0MB)
   used     = 0 (0.0MB)
   free     = 8388608 (8.0MB)
   0.0% used
PS Old Generation
   capacity = 268435456 (256.0MB)
   used     = 66860552 (63.76319122314453MB)
   free     = 201574904 (192.23680877685547MB)
   24.907496571540833% used

40435 interned Strings occupying 4567600 bytes.

Eden区 就是我们每次new出来 在堆中使用的内存区域

方式二:JDK 提供的 jconsole.exe

方式三 jps + jstat

常量池(constant pool)

指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

B站资源:https://www.bilibili.com/video/BV1yE411Z7AP

特殊说明: 解决问题的光鲜,藏着磕Bug的痛苦。 万物皆入轮回,谁也躲不掉! 以上文章,均是我实际操作,写出来的笔记资料,不会出现全文盗用别人文章!烦请各位,请勿直接盗用!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是JVM?
  • JVM优势:
  • 内存泄漏
  • JVM、JRE、JDK 关系
  • JVM 结构
  • JVM的内存划分
  • 程序计数器 Program Counter Register
  • 虚拟机栈 (栈帧:先进后出)
  • 栈问题辨析:
    • 1)垃圾回收是否涉及栈内存?
    • 2)栈内存分配越大越好吗?(就是启动命令加上参数 -Xss就是设置的栈大小)例如 -Xss1m、-Xss1024k 、-Xss1048576
    • 3)方法呢的局部变量是否线程安全
    • 4)栈内存溢出 (推荐使用 -Xss256k 指定栈内存大小!)
    • 线程运行诊断
  • 本地方法栈
    • 堆 Heap
      • 2)堆内存溢出
    • 堆内存诊断分析
      • 方式一:
      • 方式二:JDK 提供的 jconsole.exe
    • 方式三 jps + jstat
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档