赞
踩
同时,任何可以通过 Java 编译的语言,比如说 Groovy、Kotlin、Scala 等,都可以在 JVM 上运行。
类加载器:负责从文件系统、网络或其他来源加载 Class 文件,将 Class 文件中的二进制数据读入到内存当中。
运行时数据区: JVM 在执行 Java 程序时,需要在内存中分配空间来处理各种数据,这些内存区域主要包括方法区、堆、栈、程序计数器和本地方法栈。
执行引擎: 执行引擎是 JVM 的心脏,负责执行字节码。它包括一个虚拟处理器,还包括即时编译器(JIT Compiler)和垃圾回收器(Garbage Collector)。
堆
和栈
堆
、方法区
、程序计数器
、虚拟机栈
、本地方法栈
、等。方法区
和堆
是线程共享区,虚拟机栈
、本地方法栈
和程序计数器
是线程私有的。新生代
、老年代
、Eden空间
、From Survivor空间
、To Survivor空间
等名词两种方式:引用计数算法、可达性分析算法
引用计数算法:
可达性分析算法:
部分收集(Partial GC):指目标不是完整收集整个 Java 堆的垃圾收集,其中又分为:
新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS 收集器会有单独收集老年代的行为。
混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有 G1 收集器会有这种行为。
整堆收集(Full GC):收集整个 Java 堆和方法区的垃圾收集。
一共有6种触发条件:
老年代可用的连续内存空间
< 新生代历次Young GC后升入老年代的对象总和的平均大小
,说明本次 Young GC 后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间,那就会触发 Full GC。一共有四种情况:
长期存活的对象将进入老年代:在对象的对象头信息中存储着对象的迭代年龄,迭代年龄会在每次 YoungGC 之后对象的移区操作中增加,每一次移区年龄加一.当这个年龄达到 15(默认)之后,这个对象将会被移入老年代。
#可以通过这个参数设置这个年龄值。
- XX:MaxTenuringThreshold
大对象直接进入老年代:有一些占用大量连续内存空间的对象在被加载就会直接进入老年代.这样的大对象一般是一些数组,长字符串之类的对。
#HotSpot 虚拟机提供了这个参数来设置。
-XX:PretenureSizeThreshold
动态对象年龄判定:HotSpot 虚拟机并不是永远要求对象的年龄必须达到- XX:MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代
空间分配担保:假如在 Young GC 之后,新生代仍然有大量对象存活,就需要老年代进行分配担保,把 Survivor 无法容纳的对象直接送入老年代。
CMS 收集齐的垃圾收集分为四步:
优点:CMS 最主要的优点在名字上已经体现出来——并发收集、低停顿。
缺点:CMS 同样有三个明显的缺点。
Mark Sweep(标记-清除) 算法会导致内存碎片比较多
CMS 的并发能力比较依赖于 CPU 资源,并发回收时垃圾收集线程可能会抢占用户线程的资源,导致用户程序性能下降。
并发清除阶段,用户线程依然在运行,会产生所谓的理“浮动垃圾”(Floating Garbage),本次垃圾收集无法处理浮动垃圾,必须到下一次垃圾收集才能处理。如果浮动垃圾太多,会触发新的垃圾回收,导致性能降低。
G1 主要解决了内存碎片过多的问题
解释和编译的区别?
解释执行和编译执行的区别?
一个类从被加载到虚拟机内存中开始,到从内存中卸载,整个生命周期需要经过七个阶段:
加载 (Loading)
连接:
初始化 (Initialization)
使用(Using)
卸载(Unloading)
除去使用和卸载,就是 Java 的类加载过程。这 5 个阶段一般是顺序发生的,但在动态绑定的情况下,解析阶段发生在初始化阶段之后。
载入过程中,JVM 需要做三件事情:
java.lang.Class
对象,作为方法区这个类的各种数据的访问入口。JVM 会在该阶段对二进制字节流进行校验,只有符合 JVM 字节码规范的才能被 JVM 正确执行。
VM 会在该阶段对类变量(也称为静态变量,static 关键字修饰的)分配内存并初始化,对应数据类型的默认初始值,如 0、0L、null、false 等。
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。
该阶段是类加载过程的最后一步。在准备阶段,类变量已经被赋过默认初始值,而在初始化阶段,类变量将被赋值为代码期望赋的值。换句话说,初始化阶段是执行类构造器方法(javap 中看到的 <clinit>
() 方法)的过程。
双亲委派模型的工作过程:
答案是为了保证应用程序的稳定有序。
例如类 java.lang.Object,它存放在 rt.jar 之中,通过双亲委派机制,保证最终都是委派给处于模型最顶端的启动类加载器进行加载,保证 Object 的一致。反之,都由各个类加载器自行去加载的话,如果用户自己也编写了一个名为 java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中就会出现多个不同的 Object 类
如果不想打破双亲委派模型,就重写 ClassLoader 类中的 fifindClass()方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。而如果想打破双亲委派模型则需要重写 loadClass()方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。