JVM运行内存分配——拨云见日

2/22/2017来源:ASP.NET技巧人气:1325

自从上次咸菜给窝头讲解了算法的神奇后,窝头就好像变了一个人,游戏不玩了,看见校园的妹纸也不回头了,一门心思爱上了编程,这不昨天刘老师给布置了一项作业–了解java虚拟机(JVM)的内存分配。大清早就叫上学霸咸菜去了图书馆。 咸菜:“窝头星期天,能不能省点心,这么早就叫我起来,人家昨天看了半夜的韩剧还没睡醒呢!” 窝头:“哎呀!咸菜,我好不容易准备洗心革面,好好学习,你就帮帮我吧!” 咸菜心想,这样下去这孩子会不会学傻掉?都到图书馆了,看来今天是跑不掉了。 咸菜:“好吧,本姑娘见你迷途知返,就当一回司机,带带你” 窝头心喜说道:“老司机就是稳!” 二人来到图书馆,二话没说找到一个安静的角落做了下来,咸菜从书包里 掏出一本书《深入理解JAVA虚拟机》对窝头说:“给你,有时间看看吧” 窝头:“咦!这是啥呢?” 咸菜说:“这本书讲解了java在进行程序运行的时候JVM都做了什么,有助于呢理解java语言,不过这本书有点深奥,不急慢慢来” 咸菜又说:“今天就先给你讲讲一些比较浅显的虚拟机内存的分配吧” 窝头:”咸菜,你真厉害!“ 咸菜白了窝头一眼说:“别拍马屁,好好听我说” 咸菜:“窝头我问你?为什么java为什么这么流行?” 窝头:“我知道,java语言具有良好的跨平台性,可以在各大主流系统上运行” 咸菜:“那它又是怎么做到跨平台的呢?” 窝头:“这个我还真没多想” 咸菜:“java之所以能够跨平台是以为存在JVM,java的程序是交给JVM来执行的,我给你画个图讲解一下java执行的过程” 这里写图片描述 咸菜:“java源文件首先会被java编译器编译成java字节码文件(.class文件),然后交给JVM中的类加载器加载类的字节码文件,交给执行引擎去执行,JVM在执行的过程中会需要一段空间存放执行期需要的数据,这段空间就叫Runtime Data Aera(运行时数据)” 窝头:“原来java是这样保证跨平台的啊,那么运行时数据区又是怎么进行java程序的数据处理的呢” 咸菜:“在java运行时数据的区域划分,通常有如下几块: 程序计数器PRogram Counter Register)、java堆栈(Stack)、java堆(Heap)、方法区(Method Area)、本地方法栈(Native Method Stack),如下图:” 运行时数据区 窝头:“那么运行时数据区是怎么对数据进行操作的?” 咸菜:“ 1.程序计数器(Program Counter Register) 程序计数器是为了保证多线程在获得CUP执行时间过程中,线程来回切换能够保证线程能够恢复到切换前的执行位置,就说明每个线程都有自己私有的程序计数器,就是用来指示执行哪条指令的。 2.java栈(Stack) 这个就厉害了,不要看它的空间不是太大,可是它的执行的速度是超快的,当然没有CPU那么快拉,它主要用来存放局部变量(定义在函数中的变量包括:形参和函数中定义的非静态变量)和基本数据类型,每当一个函数被调用的时候就会在栈中对应的创建一块空间,它们遵循先进后出的原则,在函数使用完成后,java垃圾回收机制会将其自动清除栈,以防它占用空间(这就是以前跟你将的递归会导致内存溢出的原因)。 3.本地方法栈(Native Method Stack ) 它和上面的栈的功能其实是差不多的只不过,它服务的对象不是java程序而是本地方法,在HotSopt虚拟机中将栈和本地方法栈合二为一了。 4.堆(Heap) 堆是用来存放对象本身和数组的(数组的引用变量是自栈中),对象的实例变量是存放在堆上的(引用变量默认为null,整型默认为0,浮点型默认为0.0,布尔型默认为false),对象不再使用的时候会被java垃圾回收机制标记为特殊的记号,等待被回收,惨吧!对象的生命周期取决于程序员 窝头:”对象好惨啊!“ 咸菜:”出个题考考你“ 窝头:”好啊好啊“ 咸菜写下代码: 这里写图片描述

咸菜:”窝头,你说a等于几?x[0]等于几?“ 窝头不屑的说:”这还不简单,a=11,x[0]=1“ 咸菜:”你个猪头,x[0]=8“ 窝头:”弄啥呢?咋会等于8呢?“ 咸菜:”a和b是存放在栈中的但是数组的本身是存在堆上的,数组的引用是在栈上的,堆会给数组开辟一块空间存放数组的元素,会返还给x一个地址,x就是通过地址操控数组的,当int[]y=x的时候,x就把指向数组的地址copy给y,这样就说明名它们俩其实是指向同一个数组,当y对数组元素进行替换时,数组元素就被改变,所以在获取数组元素的时候,得到的就是替换后的数据了。“ 窝头:”这样啊,下次可得小心了“ 咸菜:”除了上面四块区域还有一块区域叫方法区(Method Area),方法区在运行内存中还是挺重要的,在方法区中,存储了类的名称,函数的心信息,字段信息,静态变量,常量和编译后的代码;在方法区中有一个部分是很重要的就是常量池。“ 窝头:”常量池是干嘛的?咸菜“ 咸菜:”这个说起来话就多了,也是面试的时候面试官常考的点,找个时间给好好说说,它是在类或接口的常量池的运行是的表现形式,,在类和接口被加载到JVM后被创建出来,我们常说的常量池指运行时常量池“ 窝头:”咸菜,为啥呢啥都知道呢?“ 咸菜:”哼,也不看看我是谁“ 未完待续...... 注:方法区和java堆是被所有线程共享的区域 参考资料:http://blog.csdn.net/u013510614/article/details/51896916?locationNum=5&fps=1