JVM初步入门(很初级,建议只做大致了解用)
jvm初步入门
本博客中的所有内容都是来自b站狂神说视频教程,如有侵权联系我删除。
下面是视频链接:b站狂神说
关于jvm的几个小问题
1. jvm的位置:
jvm是一个运行在操作系统上的用c语言编写的虚拟机(就好像是一个软件。)我们写的java软件在jvm上运行。
2. jvm的体系结构:
3. 类加载器:
作用:
加载class文件~
加载顺序
-
虚拟机自带的加载器
-
启动类(根)的加载器
-
扩展类加载器
-
应用程序加载器
4. 双亲委派机制:
双亲委派机制就是java中,当一个类要被加载的时候,会先从应用程序加载器加载,然后再去3,2,1中,去找有没有我们需要的方法。如果2中没有,就用3中的方法,如果3中没有就用4中的方法。当后加载的抛异常,才会用先加载的。
这同时也说明了java= c++– 封装了c++中的指针,内存管理,垃圾回收。。。。
5. 沙箱安全机制:
1. 什么是沙箱?
沙箱就是限制程序运行的一个环境
在类加载之前,保证有一些代码不会被加载。来保护java jvm不会被破坏
6. native
navtive表示调用java之外的东西为自己所用。其他的语言(最初是为了调用C,C++)。native会调用JNI,通过JNI来调用系统中的东西。
7. 方法区有哪些东西?
方法区中只有:static,final,CLass,常量池~
栈:一种数据结构
程序=数据结构+算法
栈:先进后出,后进先出。(就好像一个桶)
队列:先进先出
java程序在开始运行的时候,先把main方法放到栈中,再由main方法去调用其他需要的方法,如果main方法被弹出栈,程序也就运行结束了。
栈溢出
方法之间循环调用,不停的把方法放入栈中,导致,栈储存满,这样就会栈溢出。
当一个方法运行结束后,就会被弹出栈,当main被弹出栈,程序运行结束。
当一个线程结束,栈内存就会被释放,对于栈来说,不存在垃圾回收问题。
程序正在运行的方法,一定在栈的顶部
栈+堆+方法区的交互关系:
三种jvm
我们通常用的都是Java HotSpot(TM)这个虚拟机,他是由sun提供的虚拟机。
堆
一个jvm只有一个堆内存,堆内存的大小是可以调节的
类加载器读取类文件后,一般会把什么东西放到堆中?
类,方法,常量,变量~,保存我们所有引用类型的真实对象。
堆内存的三个区域
-
新生区 (young/new)
新生区分为伊甸园区、幸存0区、幸存1区。
只有在幸存0区或者幸存1区经过十几次循环的数据,才会进入养老区
上面这个循环的过程叫做轻gc
-
养老区 (old)
上面的数据到养老区就会进行一次重gc(full GC)
经过上面的筛选之后的数据会进入养老区,当养老区快要满时(整个堆都款要播爆了!),就会爆OOM
-
永久区 (perm)
方法区(非堆)就在元空间中存放
在jdk8之后,永久区改名叫做元空间
GC垃圾回收主要在伊甸园区和养老区。
假设内存满了,OOM,堆内存不够。
新生区
类诞生和成长的地方,甚至死亡(当第一次被垃圾回收之后就会死亡)
-
伊甸园区:
所有的对象都是在伊甸园区被new出来的
-
幸存区(0区,1区):
永久区(元空间)
这个区域用来存放jdk自身携带的一些class文件,interface元数据主要用来存储java运行时的环境。这个区域不存在垃圾回收!关闭jvm的时候才会释放这个区域的内存。
如果一个程序报OOM错误要怎么处理?
-
尝试扩大堆内存,看结果。
-
分析结果,看一下哪个地方出现了问题(专业工具)
上面说的专业工具就是jprofiler,利用这个在jvm中让他生成dump文件,然后利用jprofiler来查看dump文件。具体的问题出现在哪里。
GC:垃圾回收
gc垃圾回收大部分回收的都是新生代,然后是幸存区,老年区
gc分两种:轻gc和重gc
GC垃圾回收常用的算法:
引用计数法(太low了,不高效)
给堆里的方法添加一个计数装置,记录每个方法的使用此时,清除掉没有被使用的方法。py多用这种方法来回收垃圾。
- 好处:可以回收垃圾。
- 坏处:占用了新的内存空间,来计数。而且会产生垃圾碎片。
复制算法
把新生代分成两块区域,使两个区域不断的复制,用这种方法来不断的进行轻gc。
- 好处:不会产生垃圾碎片。
- 坏处:减少了一半的空间。
标记清除压缩算法:
先进行一次扫描,扫描到所有需要用到的方法,给他们标记。
然后再进行一次扫描,清除掉没有用到的方法。
又进行一次扫描,把标记的方法全部移动到一块区域,然后清除掉除这以外的区域。
- 好处:垃圾清理干净,压缩后不会有垃圾碎片。
- 坏处:需要进行多次扫描。耗费性能。
没有最好的垃圾清理算法,只有最合适的算法。
JMM Java Memory Model(java内存模型):
缓存的一致性协议,用于定义数据读写的规则。
JMM定义了线程的工作内存和主内存之间的抽象关系。
利用volatite关键字解决共享对象可见性,保证数据一致性。