java虚拟机学习笔记 一

Java技术体系包括:

1.Java程序设计语言

2.各种硬件平台上的Java虚拟机

3.Class文件格式

4.Java API 类库

5.来自商业机构和开源社区的第三方Java类库

可以把1,2,4统称为JDK,是用于Java程序开发的最小环境。  可以吧Java API中的Java SE API和Java虚拟机统称为JRE,是支持Java程序运行的最小环境。

Java虚拟机发展历史;

1.Sun Classic /Exact VM

Classis VM 与jdk4退出了历史舞台,只能使用纯解释器方式来执行Java代码,如果要使用JIT(Just IN TIme)编译器,就必须使用外挂。但是使用了JIT,JIT编译器就完全接管了虚拟机的执行任务,解释器便不再工作了,这就意味着如果要使用编译器执行,编译器就不得不对每一个方法,每一行代码都进行编译,而无论它们执行的频率是否具有编译的价值。执行效率差。

Exact VM具备了高性能虚拟机的雏形,两级即时编译器,编译器与解释器混合工作模式等。它使用准确式内存管理而得名,可以知道内存中某个位置的数据具体是什么类型,但是很快被更优秀的HotSpot VM所取代。


2Sun HotSpot VM

既继承了前两款VM的优点,也有新的技术,例如热点代码探测技术,可以通过执行计数器找出最具有编译价值的代码,然后通知JIT编译器以方法为单位进行编译。如果一个方法被频繁调用,或方法中有效循环次数很多,将会分别触发标准编译和OSR(栈上替换)编译动作。通过编译器和解释器协调的工作,可以在最有的程序响应时间和最佳执行性能中取得平衡。


---------------------------------------------------------------------------------------------

运行时数据区域


1.程序计数器

“线程私有”的内存,当前线程所执行的字节码的行号指示器。字节码解释器工作室就是通过改变这个计数器的值来选取下一条执行的字节码指令。

2java虚拟机栈

也是线程私有的,是描述java方法执行的内存模型,每个方法执行时都会创建一个Stack Frame,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。通常说的堆栈可能就是指虚拟机栈中局部变量表这部分。

局部变量表所需的内存空间在编译器完全分配。 当线程请求栈深度大于最大允许的深度抛出StackOverflowError异常,如果可以动态扩展,如果扩展时无法申请足够的内存,抛出OutOfMerory异常。

3本地方法栈 

发挥的作用和java虚拟机栈相同,为native方法服务。

4Java堆(heap)

是被所有线程共享的一快内存区域。虚拟机启动时创建,唯一目的就是存放对象实例数组,但是随着Jit编译器的发展和逃逸分析技术的发展,栈上分配和标量替换优化技术使得这个也不是那么绝对了。

也被称作GC堆,基本都采用分代收集算法,可以细分为新生代和老年代。再细分可以是Eden空间,Form Survivor空间 ToSurvivor空间等。

堆中可能划分出多个线程私有的分配缓冲区。

可以扩展通过制定(-Xmx和-Xms)

5方法区(也可以称为 Permanent Generation永久代,用永久代来实现方法区)

是各个线程共享的,用于存放已被虚拟机加载的类信息、常量。静态变量、JIT编译后的代码等数据。

6运行时常量池

是方法区的一部分,Class文件中有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用。这部分内容在类加载后在运行时常量池中存放。具有动态性,不要求常量一定是编译期产生的。例如String的Intern()方法。

7直接内存

不属于虚拟机。例如NIO类,基于通道和缓冲区的IO方式,可以使用Native函数库直接分配堆外内存。


----------------------------------------------------------------

对象的创建

虚拟机遇到一条new指令时,首先去检查指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有必须先执行类加载。

类加载完毕后分配确定的的对象内存,初始化为0值。接下来对对象进行必要的设置,对象是哪个类的实例,如何找到类的元数据,对象的GC分代年龄等。这些信息存放在对象头中。   然后执行init方法。。。


对象的内存布局

可分为三块区域 对象头(第一部分储存自身的运行时数据Mark Word,另一部分是类型指针,即对象指向它的类元数据的指针) 实例数据 对齐填充。


---------------------------------------------------------------------


垃圾回收 (Garbage Collection)

1.引用计数法

实现简单,判断效率较高,存在循环引用不能回收的问题。

2可达性分析算法

通过一系列的称为“GC Roots”的对象作为起点。从这些起点开始搜索,走过的路径称为引用链,当一个对象是不可达时,证明此对象不可用。

常见的GC ROOT

 虚拟机栈中(本地变量表)引用的对象  方法区类静态属性和常量引用的对象   本地方法栈中JNI引用的对象。

引用的类型
强引用(Strong Reference)

类似于 Object a=new Object() 只要强引用存在 ,Gc永远不会回收。

软引用(Soft Reference) SoftReference类

描述还有用但非必须的对象。系统在发生内存溢出异常之前,将会对这些对象列进回收范围内进行二次回收。

弱引用   WeakReference类

描述非必须的对象。引用的对象只能生存到下一次gc之前。

虚引用  PhantomReference类

完全不会对其生存周期产生影响,也无法通过虚引用获得对象实例,唯一作用就是对象在GC前会得到一个通知。

当对象不存在任何引用是 标记两次才会真的回收,第一次标记并进行一次删选 条件是是否有必要执行finalize()方法(没有 或者已经执行过都不会再执行)。

需要执行会放到F-Queue队列中,低优先级线程会去执行它但并不保证执行完成。


------------------------------------------

垃圾收集算法

1标记-清除算法(Mark-Sweep)

分为标记所有需要回收的对象和清除两个阶段。    有两个不足 一是效率不高,标记和清除效率都不高。 二是 空间问题,会产生大量碎片。


2复制算法(新生代所使用的)

把存货的对象复制到另一块上,并清空本块,

ibm公司研究表明新生代的对象98%是朝生夕死的,可将内存划分一快Eden区域 和两块Survivor区域,默认比例是 8 :1 :1,每次只使用eden和其中一块的Survivor空间,

当复制时Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保也就是进入老年代。


3标记-整理算法

复制算法在对象存活率较高时需要较多复制操作,效率会变低。不想让费50%空间需要有额外空间进行担保。

清除过程为让所有存活的对象都向一端移动


当前商业虚拟机都采用分代收集算法,(Generational Collection) 根据对象存活周期不同将内存划分为几块 一般是新生代和年老代 然后采用适当的收集算法。





  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值