java类加载过程(*)
Java 的类加载过程可以分为 5 个阶段:载入、验证、准备、解析和初始化。 1)Loading(载入) JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是 class 文件、也可能是 jar 包,甚至网络)转化为二进制字节流加载到内存中,并在堆中创建生成一个代表该类的 java.lang.class 对象。 2)Verification(验证) JVM 会在该阶段对二进制字节流进行校验,只有符合 JVM 字节码规范的才能被 JVM 正确执行。该阶段是保证 JVM 安全的重要屏障,下面是一些主要的检查。- 文件格式的验证:确保二进制字节流格式符合class文件的格式规范。
- 元数据验证:对类的元数据信息进行语义校验,保证不存在不符合Java语言规范的元数据信息。
- 字节码验证:通过数据流和控制流分析,确定程序语义是合法的对数据类型做出验证,
- 符号引用验证:
跨平台原理
Java源文件(.java文件) ----编译----> 通用的Java字节码(.class文件) ----JVM翻译---->平台相关的机器码 ---调用本地方法库---> 执行相应方法 每种操作系统的解释器都是不同的,但基于解释器实现的虚拟机是相同的,虚拟机识别平台并将字节码转换成机器码,这也是Java能够跨平台的原因。JVM内存模型
1. 线程私有: 2. 线程共有:- 堆(Heap,是完全二叉树):类的对象,new开辟,GC回收。
GC的内存区域
堆+方法区 JVM用Java堆的永久代来实现方法区,便于垃圾收集器用管理堆的方式管理方法区的回收GC过程
新生代的MinorGC: 新生代 = Eden (8/10) + SurvivorFrom(1/10) + SurvivorTo(1/10) Eden区:Java新创建的对象首先会被存放在Eden区,大对象则直接将其分配到老年代。在Eden区的内存空间不足时会触发MinorGC,对新生代进行一次垃圾回收。 ServivorTo区:保留上一次MinorGC时的幸存者。 ServivorFrom区:复制算法的过渡区,将上一次MinorGC时的幸存者作为这一次MinorGC的被扫描者 新生代的GC过程叫作MinorGC,采用复制算法实现,具体过程如下。 (1)把在Eden区和ServivorFrom区中存活的对象复制到ServivorTo区。如果某对象的年龄达到老年代的标准(对象晋升老年代的标准由XX:MaxTenuringThreshold设置,默认为15),则将其复制到老年代,同时把这些对象的年龄加1;如果ServivorTo区的内存空间不够,则也直接将其复制到老年代;如果对象属于大对象(大小为2KB~128KB的对象属于大对象,例如通过XX:PretenureSizeThreshold=2097152设置大对象为2MB,1024×1024×2Byte=2097152Byte=2MB),则也直接将其复制到老年代。 (2)清空Eden区和ServivorFrom区中的对象。 (3)将ServivorTo区和ServivorFrom区互换,原来的ServivorTo区成为下一次GC时的ServivorFrom区。 老年代的MajorGC: 主要存放有长生命周期(年龄大于15)的对象和大对象 JVM会进行一次MinorGC,再进行MajorGC,MajorGC标记清除算法容易产生内存碎片。在老年代没有内存空间可分配时,会抛出Out OfMemory异常。 永久代: 内存的永久保存区域,主要存放Class和Meta(元数据)的信息。GC不会在程序运行期间对永久代的内存进行清理,会因加载的Class文件过多时会抛出Out Of Memory异常。 Java 8中永久代已经被元数据区(也叫作元空间)取代。元空间直接使用操作系统的本地内存,不再受JVM的最大可用内存(MaxPermSize)空间决定,由操作系统的实际可用内存空间决定。GC的对象判定
(判断一个对象是否存活,是否该回收)
1. 引用计数:每个对象有一个引用计数属性,计数为0时可以回收。无法解决对象相互循环引用问题 2. 可达性分析:从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象要经过至少两次标记才能判定其是否可以被回收。GC算法
1、 标记-清除算法(Mark-Sweep):为每个对象存储一个标记位,在标记阶段,计数为0时记录死亡;清除阶段,该阶段对死亡的对象进行清除,。效率比较低(递归与全堆对象遍历)、碎片多。 2、 标记-压缩法(Mark-Compact):在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;清除阶段,将所有存活的对象整理一下,放到另一处空间,然后把剩下的所有对象全部清除。减少碎片,但复制操作耗时。 3.、复制算法(copying):将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。长时间存活的对象来回复制耗时,适用于小对象、生存时间短的区域。 4. 分代收集(Generational Collecting): 新生代:对象生存期短,每次回收都会有大量对象死去,采用复制算法。 老年代:对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。垃圾收集器
内存回收算法的具体实现 1、 Serial收集器:串行单线程,新生代复制算法、老年代标记-压缩 2、 ParNew收集器:并行版本Serial收集器 3、 Parallel Scavenge收集器:通过自适应调节策略提高系统吞吐量,三个重要参数:控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数,控制吞吐量大小的-XX:GCTimeRatio参数和控制自适应调节策略开启与否的UseAdaptiveSizePolicy参数 4、 CMS(Concurrent Mark Sweep) 收集器: 是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重新标记,并发清除,收集结束会产生大量空间碎片。 (1)初始标记:只标记和GC Roots直接关联的对象,速度很快,需要暂停所有工作线程。 (2)并发标记:和用户线程一起工作,执行GC Roots跟踪标记过程,不需要暂停工作线程。 (3)重新标记:在并发标记过程中用户线程继续运行,导致在垃圾回收过程中部分对象的状态发生变化,为了确保这部分对象的状态正确性,需要对其重新标记并暂停工作线程。 (4)并发清除:和用户线程一起工作,执行清除GC Roots不可达对象的任务,不需要暂停工作线程。 5、 G1收集器: 前沿成果,标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。不会产生空间碎片,可以精确地控制停顿。 CMS收集器使用“标记-清除”算法,是老年代的收集器,以最小的停顿时间为目标的收集器。 G1收集器使用的是“标记-整理”算法,范围是老年代和新生代,进行了空间整合,降低了内存空间碎片。对象的引用类型
一切皆对象,对象的操作是通过该对象的引用(Reference)实现的, Java中的引用类型有4种,分别为强引用、软引用、弱引用和虚引用 (1)强引用:最常见。在把一个对象赋给一个引用变量时,这个引用变量就是一个强引用。有强引用的对象一定为可达性状态,所以不会被垃圾回收机制回收。因此,强引用是造成Java内存泄漏(Memory Link)的主要原因。 (2)软引用:软引用通过SoftReference类实现。如果一个对象只有软引用,则在系统内存空间不足时该对象将被回收。 (3)弱引用:弱引用通过WeakReference类实现,如果一个对象只有弱引用,则在垃圾回收过程中一定会被回收。 (4)虚引用:虚引用通过Phantomreference类实现,虚引用和引用队列联合使用,主要用于跟踪对象的垃圾回收状态。版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。