个人理解仅供参考
位置?
位于操作系统之上。
三种jvm?
SUN公司的HotSpot-最多
BEA公司的JRockit
IBM公司的J9 VM
调优调哪里?-heap
99%调堆内存。栈是100%不会有垃圾的。
类加载器?
加载class文件,一个对象只有一个Class,Class是一个模板。
1.虚拟机自带的加载器
2.启动类加载器-rt.jar内的
3.扩展类加载器-\jre\lib\ext下的
4.应用程序加载器-classpath:下的,一般程序员写的业务就在这里加载
null:调不到,是因为用C C++写的
java = C++--,java就是去掉C繁琐的针织和内存管理。
双亲委派机制?安全
类加载器收到加载的请求,将这个请求委托给父类加载器去完成,一直向上委托,直到启动类加载器Boot加载器,启动类加载不了在逆着向下加载,直到加载完成,如果还加载不完成就报错Class Not Found。
和string同名同包,定义这个类执行报错。
当执行的时候先去找App-Ext-Boot,最终在Boot下执行因此报错,会优先让Boot去加载,此时会执行java.lang下的String类的方法因此说找不到main方法。
当在Boot下找不到的时候会再去Ext下找找不到再去App下找。
沙箱安全机制sandbox?了解即可
字节码校验器:确保java类文件遵守java语言规范。并不是所有的文件都经过字节码校验器比如说核心类(java自己的类比如string因为已经校验过了)。
类装载器:
双亲委派机制。
将代码归入保护域,确定代码可以进行哪些操作。
native?
扩展java类的使用,融合不同的编程语言为我所用。最初是想融合C C++
在内存中专门开辟了一块本地方法栈Native Method Stack,存储本地方法
创建一个thread,点进去会看见start0()方法,start0()方法就是native方法。
被native修饰的方法会去调用底层C,本地方法栈->本地接口(JNI)->本地方法库。
方法区?
被所有线程共享的,所有定义方法的信息都保存在此区域,属于共享区间。
栈?stack
先进后出,后进先出。桶。
每个线程会创建一个栈,线程结束栈也随之结束,每个栈内的数据是私有的。
栈不参与垃圾回收,生命周期短暂,通过栈帧来运行切换。
存储对象:局部变量+对象的引用+实例方法。也就是方法内的东西和方法引用。
队列?FIFO
先进先出。管道。
main方法先执行最后结束?
压栈,main先进去然后开始调其他业务方法。
StackOverflowError栈溢出?
递归去调方法,栈内被压入很多方法。
堆-heap?
一个jvm只有一个heap,stack是线程级别的可以有多个。
堆大小可以调节。
- 年轻代:类诞生死亡区域。
- 老年代:过渡区域。
- 元空间:杀不死的。常驻内存。逻辑上存在,物理上不存在。
堆内存调节:-Xms1024m -Xmx1024m -XX:+PrintGCDetails
堆、栈、方法区对比?
堆:
提供所有类实例和数组对象存储区域。
jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。
栈区:
每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中。
每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
方法区:
又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
运行时常量池都分配在 Java 虚拟机的方法区之中。
手绘图便于理解仅供参考:
常用工具:
查看jvm内存占用情况:
jps查看进程号
jmap -heap id