java虚拟机学习笔记

java虚拟机是java为实现一处编译多处执行机制而模拟出的一个机器,因其,java语言得到了广大编程者的喜爱,也因其,java语言的应用受到一定程度的限制。但,我们必须承认java虚拟机的机制使得java编程人员编写代码时节省了很多内存控制的操作。
[b]虚拟机内存管理机制[/b]
虚拟机主要包括运行时数据区域、执行引擎、本地库接口、本地方法库等部分。在虚拟机运行期间会将虚拟机内存分配为若干区域:线程共享区域(方法区域、堆)、线程独享区域(虚拟机栈、程序计数器、本地方法栈)
程序计数器其为一块很小的内存空间,主要用来记录线程执行字节码的行号。
虚拟机栈在java方法执行期间压入相关信息:局部变量表、操作栈、动态链接、方法出口等信息。
本地方法栈其功能与虚拟机栈相似,只不过它为jni(本地方法接口)服务。
以上三个区域都为线程独立区域,即其生命周期为线程启动到线程死亡。
方法区域和虚拟机栈则是线程共享区域,他们在虚拟机启动时就已分配,生命周期伴随虚拟机启动到关闭。
方法区域主要存放类加载器加载的类信息、静态变量、常量等信息,值得注意的是本区域还包括一个运行时常量池,用于存放字面常量与符号引用信息。
堆应该是虚拟机内存调优最重要部分,虚拟机垃圾回收机制的工作重点应该在于堆。本区域主要存放程序运行期间生成的对象实例。
上面简单介绍了虚拟机的内存管理机制,接下来对虚拟机垃圾回收做一些总结。
[b]垃圾回收机制[/b]
垃圾回收是java程序得意顺利运行的一种保障,但是不是说垃圾回收的存在就可以保证虚拟机内存不发生溢出等异常。
垃圾回收机制不是由java独创的,早在java诞生前就已经存在。
垃圾回收需要考虑三个问题:回收什么,什么时候回收,怎么回收。
对于java程序来说,需要回收内存中已经不需要的部分,那么如何确定变量已经不需要呢?一种简单的算法为“引用计数法”,即对一个变量引用一次就对其计数加一,当其引用计数为0时就表示该变量无用。这种算法简单且效率很高,但它有一个致命的缺陷,就是它不能解决循环引用问题,例如:
pulic class ReferenceCountGc {
ReferenceCountGc instance = null;
public static void testGc(){
ReferenceCountGc objA = new ReferenceCountGc();
ReferenceCountGc objB = new ReferenceCountGc();

objA.instance = objB;
objB.instance = objA;

objA = null;
objB = null;
System.gc();
}
}
对于上面的代码,显然objA和objB都属于无用变量,但是他们间存在循环引用,导致引用计数在其失效时不为零,所以引用计数算法没有将其回收,好在java虚拟机的垃圾回收机制不是引用计数算法,而是“根搜索算法”,所谓的根搜索个人理解就是从几个开始节点,在整个程序中向下搜索,看看都可以到达哪些节点,可以到达的节点为有用节点,而不可达的为不可用节点。
知道的回收什么,接下来就要考虑怎么回收了,java虚拟机回收算法主要有“标记清除”、“复制”、“标记整理”。
标记清除:标记清除算法较为简单,一遍标记,一遍清理,即遍历变量,找出无用变量,完后释放其占用的内存空间,效率较高,但是容易造成内存空间碎块话,即导致内存不连续,在分配大内存空间时可能报内存不足异常。
复制:复制算法算是一种牺牲内存空间得到高效回收的一种体现,它将内存空间分为两块,每次使用一块,在回收时,将上次使用块中有用变量复制到另一个备用块,如此反复。缺点很明显,很浪费内存空间。
标记整理:标记整理是在标记清除基础上得以继续衍生的算法,在垃圾回收时,其不简单的将无用变量清除,而是将有用变量向前挪动填充被清理掉的内存,使得剩余空间都在尾部,且为连续大内存。
当然了,java虚拟机的回收算法根据不同虚拟机会有不同,但是多为多种算法的综合应用。
最后是什么时候回收的问题,该为题其为制约虚拟机无隙运行的关键,现在多个虚拟机厂家也多在此下工夫,产生了很多算法,但是根据程序不同应用场景,各个算法都具备各自优缺点,所以没有一种通用算法,可以算我的效率非常高。
[b]类加载器[/b]
理解java虚拟机,其中一个模块必不可少,那就是类加载器,classloader。
类加载运行周期可分为三阶段:加载、链接、初始化三阶段,其中链接又可分为:验证、准备、解析三部分。
加载就是将虚拟机外部的class文件加载成字节码,读到内存。
验证就是检查字节码是否符合规范,有无运行危险。
准备就是对变量进行分配内存,并设初始值,此处的初始值为变量的默认值(0、null等)
解析是将符号引用变为直接引用。
初始化阶段是对变量进行初始化,即置为程序中的默认值。
加载器在加载类的方式为双亲委派模式,会依据启动类加载器、扩展类加载器、应用程序类加载器、自定义加载器为序从上而下的加载,例如,类A请自定义加载器加载,自定义加载器会将加载请求传递给父加载器,父加载器决定是否加载,仅当父加载器无法加载时,子加载器才进行加载。
鉴于对java虚拟机理解水平的限制,本次仅总结上述内容,若存在不正确的地方,还望指教。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值