文章目录
1 System.gc()的理解
-
通过system.gc()的调用,会显式触发Full Gc,同时对老年代和新生代进行回收
-
然而System.gc 无法保证对垃圾收集器的调用(相当于是只通知垃圾收集器)
2 内存溢出
没有空闲内存,并且垃圾收集器也无法提供更多内存
内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出。
2.1 原因:
-
java虚拟机的堆内存设置不够,可以通过
-Xms
,-Xmx
进行调整。 -
代码中创建了大量大对象,长时间不能被垃圾收集器收集(存在被引用)
注意:
在抛出oom之前,垃圾收集器会被触发,当然也不是任何情况垃圾收集器都会被触发,当我们分配一个超大对象时,超过堆的最大值,就会直接抛出oom。
3 内存泄露
只有对象不会再被程序用到了,但是gc不能回收他们的情况,为内存泄露。
内存泄漏:内存泄漏指程序运行过程中分配内存给临时变量,用完之后却没有被GC回收,始终占用着内存,既不能被使用也不能分配给其他程序,于是就发生了内存泄漏。
举例:
- 单例模式
单例的生命周期和应用程序一样长, 如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露。
- 一些提供close资源未关闭导致内存泄露
数据库连接,网络连接和io连接必须手动close,否则是不能进行回收的。
4 stop the world
简称stw,指的是在gc过程中,会产生程序的停顿。停顿产生时整个应用程序的线程都会被暂停,没有响应,这个称为stw。主要是为了确保数据的一致性
-
分析工作必须在一个确保一致性的快照中进行
-
如果出现分析过程中对象引用关系还在不断变化,则分析结果的准确性无法保证。
5 并发与并行
5.1 并发
- 单个cpu(单核)在进行多线程操作时,将cpu运行时间分为若干时间段,分配给各个线程执行,在一个时间点上只运行一个线程。
5.2 并行
-
当系统有多cpu时,一个cpu执行一个进程,另一个cpu执行另一个进程,两个进程相互不抢占cpu资源,可以同时进行,我们成为并行。
-
决定并行的因素不是cpu的数量,而是cpu的核心数量,一个cpu多核也可以并行
5.3 并发与并行的区别
-
并发是指两个或者多个进程在同一时间间隔内发生。并行是指两个或者多个进程在同一时刻发生
-
并发的多个任务之间是互相抢占资源的,并行的多个任务之间是不互相抢占资源。
-
只有在多cpu或者一个cpu多核情况下,才会发生并行。
6 垃圾回收的并发与并行
6.1 并行
指多条垃圾收集线程并行工作,但是此时用户线程仍处于等待状态
6.2 串行
相较于并行的概念,单线程执行。
6.3 并发
用户线程与垃圾回收线程同时执行(但不一定是并行的)
7 安全点与安全区域
7.1 安全点
-
程序执行并非在所有地方都能停顿下来开始gc,只有在特定的位置才能停顿下来,这些位置称为“安全点”
-
安全点,如果太少会导致gc等待时间太长,如果太频繁导致运行时性能问题。
怎样检查线程到最近的安全点停顿下来呢
-
抢先式中断(没有虚拟机在使用了)
-
主动式中断
设置中断标志,当运行到安全点时,就自动挂起
7.2 安全区域
主要是为了应对线程处于 sleep状态或blocked状态,这时候线程无法响应jvm中断请求
- 安全区域是指在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始gc都是安全的。