JVM
JVM是什么
jvm的定义:Java Virtual machine - java程序的运行环境(java二进制字节码的运行环境)
好处:
- 一次编写,到处运行(跨平台)
- 自动内存管理,垃圾回收功能
- 数组下标越界检查
- 多态(面向对象编程的基石)
比较:
jvm,jre,jdk
jvm和jre以及jdk的关系如下图所示:
学习JVM有什么用
- 帮助我们面试,提升我们的竞争力
- 可以帮助我们理解底层的实现原理,有助于长远发展
- 是中高级程序员的必备技能
常见JVM
如下图所示
内存结构
程序计数器
定义:Program Counter Register 程序计数器(寄存器)
java代码的执行流程:java源代码–>二进制字节码(jvm指令)–>解释器–>机器码–>cpu
作用:在指令执行过程中,记住下一条指令的执行地址
特点:
- 是线程私有的(每个线程都有自己的程序计数器)
- 不会存在内存溢出
虚拟机栈
定义:Java Virtual Machine Stacks(java虚拟机栈)
- 线程运行时需要的内存空间
- 一个栈内可以看成由多个栈帧组成
- 每个线程都只能有一个活动栈帧,对应着当前正在执行的那个方法
栈帧:每个方法运行时需要的内存
问题辨析
垃圾回收是否涉及栈内存?
不涉及,栈帧内存在调用方法结束后,会被自动回收掉
栈内存分配越大越好吗?
栈内存越大,线程数越少
方法内的局部变量是否线程安全?
- 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的
- 如果局部变量引用了对象,并逃离了方法的作用范围,就要考虑线程安全问题
栈内存溢出
- 栈帧过多导致栈内存溢出(无限递归,错误名称:java.lang.StackOverflowError)
- 栈帧过大导致栈内存溢出
IDEA中的栈内存大小设置,打开程序运行设置,找到VM options,输入参数-Xss+要设置的内存大小
线程运行诊断
案例一:cpu占用过多
linux系统中,定位:
- 用top定位哪个进程对cpu占用过高
- 使用ps H -eo pid,tid,%cpu | grep 进程号(pid:进程号,tid:线程号,%cpu:对内存占用率,grep:按条件查找),进一步定位是哪个线程引起的cpu占用过高
- jdk提供的工具,jstack+进程id,可以列出这个java进程中的所有java线程,然后根据找到的占用率最高的线程id(需要将十进制编号换算成16进制,然后进行查找线程),可以查看第几行出现问题导致占用率高
案例二:程序运行很长实际没有结果
可以使用jstack查找问题,如死锁