0
点赞
收藏
分享

微信扫一扫

Java虚拟机(JVM)结构体系

一脸伟人痣 2022-04-13 阅读 64
java

1.JVM的体系结构

 垃圾不会存在于栈和程序计数器中,只存在于方法区和堆中

所谓JVM调优 99%是对堆进行调优。(方法区是特殊的堆)

程序计数器

  1. 作用:记住下一条JVM指令的执行地址

    java源代码→二进制字节码(jvm指令)→解释器→机器码→CPU

2.特点:

程序计数器是线程私有的,随着线程创建而创建,随着线程销毁而销毁(每个线程都有自己的程序计器)

不会存在内存溢出,是一块较小的内存空间

虚拟机栈:是线程运行需要的内存空间

栈帧:每个方法运行时需要的内存

每个栈由多个栈帧组成,对应着每次方法调用时多占用的内存

每个线程只能有一个活动栈帧(栈顶部正在调用的方法),对应着当前正在执行的那个方法

问题解析

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

 No!栈帧每次结束后都会弹出栈,垃圾回收是回收堆内存。

2.栈内存分配越大越好吗?

 不是,因为增加栈大小,会造成每个线程的栈都变的很大,使得一定的栈空间下,能创建的线程数量会变小!

3.方法内的局部变量是否线程安全?

如果方法内局部变量没有逃离方法的作用访问,它是线程安全的

如果是局部变量引用了对象,并逃离方法的作用方法,需要考虑线程安全

栈内存溢出(-Xss可以设置栈内存)

1.栈帧过多 如方法递归调用却没有终止条件

2.栈帧过大 不太容易出现这种情况

3.循环引用 如员工类里包含部门,部门类里包含员工,使用JSON工具类时就会造成

  转化员工中的部门成员时,还要转化部门中的员工成员(套娃)

**线程运行诊断 **

案例:cpu占用过多

定位

 top命令可以看到是那个进程对cpu的占用过高

 ps H -eo pid,tid,%cpu | grep 进程id (进一步定位是哪个线程引起的cpu占用过高)

 jstack进程id(根据线程id找到有问题的线程,进一步定位到问题代码的代码行号)

本地方法栈

为本地方法提供运行的空间

本地方法:Native Method 不是由Java编写的方法(C或C++),与操作系统更底层的API打交道

1.Heap 堆:通过new关键字,创建对象都会使用堆内存

2.特点:

   它是线程共享的,堆中对象都需要考虑线程安全的问题

   有垃圾回收机制

堆内存诊断工具

1.jps工具

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

2.jmap工具

  查看堆内存占用情况

3.jconsole工具

 图形界面的,多功能的监测工具,可以连续监测

案例:垃圾回收后,堆内存占用依然很高

   jvrisualvm工具可以抓取堆Dump看到详细数据

方法区

所有java线程共享的区域 存储了跟类结构相关的信息 在虚拟机启动时被创建

逻辑上是堆的组成部分

 

内存溢出

1.8以前会导致永久代内存溢出

  PermGen space

 -XX:MaxPermSize 最大内存空间

1.8以后会导致元空间内存溢出(元空间默认使用的是系统内存且没有上限)

 Metaspace

场景:

 spring和mybatis中的cglib 在运行时间会产生大量的类

常量池

常量池就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息

运行时常量池,常量池是*.class文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把 里面的符号地址变为真实地址

举报

相关推荐

0 条评论