type
status
date
slug
summary
tags
category
icon
password
定义
java virtual machine,Java程序的运行环境
好处:有了java虚拟机,就可以达到一次编写,到处运行,相对于其他语言(C),有自动内存管理,可以实现垃圾回收管理
比较
jvm:java运行的环境
jre:jvm+基础类库
jdk:jvm+基础类库+编译工具
javaSE:jdk+IDE开发工具
javaEE:JDK+应用服务器+IDE工具
学习路线

内存结构
1.程序计数器

java代码在执行的时候需要把代码转换成字节码,字节码通过解释器,翻译为机器码,再交给cpu执行,程序计数器在其中起到的作用是:记录下一条jvm指令的执行地址。这样就可以按照顺序执行命令。充当程序计数器的是寄存器,寄存器读写速度快,适合频繁存放和读取指令的场景。
特点:
1.线程私有的。多线程的情况下,cpu根据时间片会来回切换线程,必须要保证程序计数器是线程私有的才会保证不会错乱,每个线程的计数器记录该线程下一个要执行的指令。
2.没有内存溢出。设计的时候就不会内存溢出。
2.虚拟机栈

栈:线程运行的内存空间
栈帧:每个方法运行所占用的内存,一个方法就是一个栈帧
在程序执行的时候,根据方法的执行顺序把栈帧压入栈,第一个方法在最底部,最后一个方法在栈顶部,方法执行完从栈顶出栈,释放内存,依次执行。
问题:
Q:垃圾回收是否涉及栈内存?
A:不涉及,栈帧执行完就出栈释放内存了,不会产生垃圾
Q:栈内存分配的越大越好吗?
A:可以通过参数给栈内存分配的大一点,每个线程对应一个栈,物理内存一定,栈内存设置越大,能成生的线程就越小。栈内存小了,线程在运行时可能会因为栈溢出(StackOverflowError)而崩溃。设置的大,每个线程存储的对象就变大。

Q:方法内的局部变量是否线程安全
A:如果是一个方法内的局部变量,因为一个线程一个栈,每个方法又是一个栈帧,所以局部变量是线程安全的,但如果局部变量用static修饰,则是线程共享的,线程都会读取这个变量,就要考虑线程安全了。
栈内存溢出:
- 栈帧过多导致栈内存溢出
- 一次调用的方法过多,栈内放入的栈帧过多导致溢出,比如递归调用
- 栈帧过大导致栈内存溢出。
线程运行诊断
cpu占用过多
用top命令看哪个进程对cpu的占用过高

2再查看哪个线程占用的内存过高,命令:ps H -eo pid,tid,%cpu | grep 45652
再用jstack命令查看是代码的哪一行
3.本地方法栈
本地方法的方法体是使用非Java语言实现的,如C语言,具体由JVM底层实现去支持。他的作用是融合不同的编程语言为Java使用,最初的设计初衷是融合C/C++语言。Java程序存在一些需要与底层系统(如操作系统或某些硬件)进行数据交互,而通过本地方法,我们可以实现在java层面与底层系统进行交互。
16节完
4.堆
5.方法区