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

来源:互联网 发布:如何找pdf 知乎 编辑:程序博客网 时间:2024/05/21 16:09

自从上次咸菜给窝头讲解了算法的神奇后,窝头就好像变了一个人,游戏不玩了,看见校园的妹纸也不回头了,一门心思爱上了编程,这不昨天刘老师给布置了一项作业–了解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

1 0
原创粉丝点击