JVM 领略着实并不难!
这段代码在JDK1.6和JDK1.7运行的功效差异。JDK1.6功效是:false,false ,JDK1.7功效是true, false。缘故起因是:JDK1.6中,intern()要了解吧初次碰着的字符串实例复制到常量池中,返回的也是常量池中的字符串的引用,而StringBuilder建设的字符串实例是在堆上面,以是肯定不是统一个引用,返回false。在JDK1.7中,intern不再复制实例,常量池中只生涯初次呈现的实例的引用,因此intern()返回的引用和由StringBuilder建设的字符串实例是统一个。为什么对str2较量返回的是false呢?这是由于,JVM中内部在加载类的时辰,就已经有"java"这个字符串,不切合“初次呈现”的原则,因此返回false。 垃圾接纳(GC) JVM的垃圾接纳机制中,判定一个工具是否衰亡,并不是按照是否尚有工具对其有引用,而是通过可达性说明。工具之间的引用可以抽象成树形布局,通过树根(GC Roots)作为出发点,从这些树根往下搜刮,搜刮走过的链称为引用链,当一个工具到GC Roots没有任何引用链相连时,则证明这个工具是不行用的,该工具会被鉴定为可接纳的工具。 那么那些工具可作为GC Roots呢?首要有以下几种: 1.假造机栈(栈帧中的当地变量表)中引用的工具。 2.要领区中类静态属性引用的工具。 3.要领区中常量引用的工具 4.当处所法栈中JNI(即一样平常说的Native要领)引用的工具。 其它,Java还提供了软引用和弱引用,这两个引用是可以随时被假造机接纳的工具,我们将一些较量占内存可是又也许后头用的工具,好比Bitmap工具,可以声明为软引用货弱引用。可是留意一点,每次行使这个工具时辰,必要表现判定一下是否为null,以免堕落。 三种常见的垃圾网络算法 1.标志-破除算法 起首,通过可达性说明将可接纳的工具举办标志,标志后再同一接纳全部被标志的工具,标志进程着实就是可达性说明的进程。这种要领有2个不敷点:服从题目,标志和破除两个进程的服从都不高;另一个是空间题目,标志破除之后会发生大量的不持续的内存碎片。 2.复制算法 为了办理服从题目,复制算法是将内存分为巨细沟通的两块,每次只行使个中一块。当这块内存用完了,就将还存活的工具复制到另一块内存上面。然后再把已经行使过的内存一次整理掉。这使得每次只对半个地区举办垃圾接纳,内存分派时也不消思量内存碎片环境。 可是,这价钱其实是让人无法接管,必要捐躯一样平常的内存空间。研究发明,大部门工具都是“朝生夕死”,以是不必要安装1:1比例分别内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次行使Eden空间和一块Survivor空间,默认比例为Eden:Survivor=8:1.新生代地区就是这么分别,每次实例在Eden和一块Survivor平分派,接纳时,将存活的工具复制到剩下的另一块Survivor。这样只有10%的内存会被挥霍,可是带来的服从却很高。当剩下的Survivor内存不敷时,可以去晚年月内存举办分派包管。怎样领略分派包管呢,着实就是,内存不敷时,去晚年月内存空间分派,然后等新生代内存缓过来了之后,把内存偿还给晚年月,保持新生代中的Eden:Survivor=8:1.其它,两个Survivor别离有本身的名称:From Survivor、To Survivor。二者身份常常变更,即偶然这块内存与Eden一路参加分派,偶然是另一块。由于他们之间常常彼此复制。 3.标志-清算算法 标志清算算法很简朴,就是先标志必要接纳的工具,然后把全部存活的工具移动到内存的一端。这样的甜头是停止了内存碎片。 类加载机制 类从被加载到假造机内存开始,到卸载出内存为止,整个生命周期包罗:加载、验证、筹备、理会、初始化、行使和卸载七个阶段。 个中加载、验证、筹备、初始化、和卸载这5个阶段的次序是确定的。而理会阶段不必然:它在某些环境下可以在初始化阶段之后再开始,这是为了支持Java的运行时绑定。 关于初始化:JVM类型明晰划定,有且只有5中环境必需执行对类的初始化(加载、验证、筹备天然再此之前要产生): 1.碰着new、getstatic、putstatic、invokestatic,假如类没有初始化,则必需初始化,这几条指令别离是指:new新工具、读取静态变量、配置静态变量,挪用静态函数。 2.行使java.lang.reflect包的要领对类举办反射挪用时,假如类没初始化,则必要初始化 3.当初始化一个类时,假如发明父类没有初始化,则必要先触发父类初始化。 4.当假造机启动时,用户必要拟定一个执行的主类(包括main函数的类),假造机遇先初始化这个类。 5.可是用JDK1.7启的动态说话支持时,假如一个MethodHandle实例最后理会的功效是REF_getStatic、REF_putStatic、Ref_invokeStatic的要领句柄时,而且这个要领句柄所对应的类没有举办初始化,则要先触发其初始化。 其它要留意的是:通过子类来引用父类的静态字段,不会导致子类初始化:
最后只会打印:SuperClass init! 对应静态变量,只有直接界嗣魅这个字段的类才会被初始化,因此通过子类类引用父类中界说的静态变量只会触发父类初始化而不会触发子类初始化。 通过数组界说来引用类,不会触发此类的初始化:
(编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |