【Java中的JVM】(待整理)

1、JVM相关

1、JVM的功能:

      a.通过ClassLoader寻找和装载class文件

      b.解释字节码成为指令并运行,提供class文件运行环境

      c.进行运行期间垃圾回收

      d.提供与硬件交互的平台

2、垃圾回收:

1)虚拟器线程等待JVM到达安全点之后出现,操作必须在独立的线程里执行,因为当堆修改无法进行时,线程需要JVM位于安全点。VMThread包括stop-the-world垃圾回收、线程栈dump、线程暂停、线程偏向锁(basicObjectLock)解除。

2)safePoint安全点可以挂起线程,防止线程无限运行,一般位于循环末尾(防止大循环)、方法返回前、调用方法的call之后、抛出异常的位置。

3)safepoint 只能处理一些正在运行的线程,对于一些sleep()或block()的线程会被添加到safe region区域。标记safe region。当它被唤醒时,应该先检查GC是否完成操作。

4)GC的时候,所有进入safepoint的线程会在一个Thread.lock锁阻塞,直到当JVM的GC完成操作,JVM释放锁,阻塞的JAVA线程才能运行。

5)GC线程:这些线程支持JVM中不同的垃圾回收活动。

6)对象的回收:对象、数组存放在JVM堆中,分为新生代和老年代。新生代分为三个区,一个Eden、两个survivor,对象创建之后存在Eden(容量很大的对象可以创建到老年代)。新生代会执行MinorGC,98%的对象会被回收,不被回收的对象转移(复制算法)到一个survivor中,然后等待下一次MinorGC,GC之后Eden剩下的对象和survivor中的对象都被转移到另一个servivor中,对象就在两个survivor中不断转换。直到经历15次MinorGC才能进入老年代(old)。old中会执行FullGC,但比MinorGC的执行频率要低很多。FullGC一般耗时为MinorGC的22.89倍。新生代一般18M,老年代一般42M。

7)垃圾回收由新生代和年长代协作,称为分代回收,分别采用复制算法和标记整理算法。

  复制算法:两个区域A和B,初始化对象在A,继续存活的对象被转移到另一个区。用在新生代的回收上。新生代分为一个Eden、两个survivor区。

  标记整理算法:一块区域,对所有的对象进行标记(可达性标记),然后回收不可达对象,因为不是复制转移算法,所以会出现碎片。整理算法可以将碎片空间进行整理,整理出更大的内存空间存放更大的独享。

7)对象的回收机制:当前对象是否回收,主要是采用可达性分析,如果不可达,会进行一个F-Queue队列之中,在finalize方法执行过程中,会进行第二次标记是否可达,选择自救还是回收。垃圾回收线程在jvm中优先级相当的低。

8)程序开发者只能推荐JVM进行回收,但何时回收,回收哪些不能控制,-->可通过system.gc()来建议gc回收。垃圾回收只是回收不再被使用的JVM内存,与内存是否溢出没有直接关系。

9)真正宣布一个对象死亡:第一次标记-->调用finalize方法-->第二次gc回收。

10)各版本的垃圾回收器:

单线程收集器,在进行垃圾收集时,必须暂停其他所有的工作线程,直到它搜集结束。

多线程收集器,

  jdk1.3  Serial New收集器:针对新生代,单线程收集器(使用复制收集算法)

  jdk1.4  Parallel New收集器:并行回收,多线程收集器(新生代和年长代采用不同的算法)。

  jdk1.4  Paraller Scavenge:并行,新生代多线程,吞吐量最大化,精确控制吞吐量。 吞吐量=运行用户代码/CPU运行时间(用户代码+垃圾回收)

  jdk1.5  CMS(Concurrent Mark Sweep)目标:最短回收停顿时间。(标记-清除)

  jdk1.5  Serial Old老年代版本,它同样是一个单线程收集器,(使用标记整理算法)

  jdk1.6  Parallel Old并行,注重吞吐量以及CPU资源敏感的场合,可以优先考虑Parallel      Scavenge+Parallel Old收集器组合。

  jdk1.7  G1并行与并发、分代收集、空间整合、可预测的停顿,有意代替GMS。(整体标记整理,局部采用复制)

11)内存泄漏(Memory leak)是指一个不再被使用的对象或者变量还在内存中占用存储空间,在java语言中引入垃圾回收机制,有GC负责进行回收不再使用的对象,释放内存。但还是会出现内存泄漏,主要有两个情况:1)堆中申请的空间没有释放,2)对象仍保留连接引用(例如数据库连接)

12)内存泄漏的原因:如数据库连接、网络连接、IO连接,不再使用时如果连接不释放容易造成内存泄漏。释放对象时往往没有删除响应的监听器,可能造成内存泄漏。

13)内存溢出(OOM)是指程序在申请内存时没有足够的内存供使用,进而导致程序奔溃。内存泄漏最终导致内存溢出。

 

2、JVM维护了一个数据结构,记录了所有的线程,所以它可以快速检查所有线程的状态。

3、JVM通过控制主内存与每个线程的本地方法内存之间的交互,为java提供内存可见性(保证线程通信)。

4、如果使用jconsole或其他调试器,会看到很多线程在后台运行,主要有JVM线程、触发main方法的主线程以及主线程创建的其他线程一起运行。

5、JVM有两种执行方法:解释型和编译型(JIT)

在JIT执行方式下,将safepoint的检查代码加入到本地代码,当JVM需要线程进入safepoint时,只需要设置标志位,运行到标志位,如果标志位被设置则进入safepoint。

在解释型执行下,JVM会设置一个2字节的dispatch tables解释器,执行过程中会经常检查这个dispatch tables,当有请求发生时,则让线程进入safepoint。

 

6、周期性任务线程:该线程负责定时器事件(也就是中断),用来调度周期性操作的执行。

7、编译器线程:这些线程在运行时将字节码动态编译成本地平台相关的机器码。

8、信号分发线程:这个线程接收发送到JVM的信号并调用适应的JVM方法处理。

 

9. 虚拟机中的线程图示:

 

 

操作系统分配给每一个线程2G的内存,2G = 堆内存+方法区+程序计数器+本地栈+线程栈

一般线程栈有1000-2000栈帧就够用于递归,如果发生内存溢出==没有多余的内容分配给新对象,可以适当的减少栈的容量,来扩大堆的容量。

 

 10. JVM中的堆栈划分:

  配置信息: -Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3 

参数含义:  

   -Xmx  ==》最大堆大小   10240

   -Xms  ==》初始化堆大小  10240

   -Xmn  ==》年轻代大小    5120

新生代包括Eden 和 Survivor 一共三个区。

   -XXSurvivorRatio ==》年轻代中Eden区和Survivor区的大小比值 

Eden区  3072     两个Survivor区 2048

 所以每个 Survivor 的大小为 1024 m







猜你喜欢

转载自blog.csdn.net/ca1m0921/article/details/80945121