JVM 运行时数据区域
C语言的阴影
还记得刚进大学的时候,以为这个世界上最难学的不过C语言了。尽管后来陆续学了很多的更难的课程,尽管慢慢掌握了计算机的很多原理之后,回头来看C语言,似乎没那么难理解,可当年初学C语言时的“阴影”,这么多年来,一直没有散去。
我经常还能想到几年前,懒散的趴在逸夫教学楼F1教室最后一排的座位上,听兰书敏老师讲着“戏院”(C语言)的场景。兰老师问到:“你们怎么都不吭声?到底是哪里听不懂?”老师,学生当时真是哪哪儿都没听懂啊。
身在Java,心在C(Java大神勿喷,C对我来说,真是一种情怀)
没想到,工作一年多的时间里,用的最多的语言不是对我影响最大的C,而是大学毕业之后现学现卖的Java。所以我对C和Java都算有一点了解。
一条有意思的Java面试题
前几天在搜索一个问题的解决方案时,偶然看到一个Java面试题,觉得网上绝大多数解释,有些浮于表面。而真神们又不屑于解释这些无聊的问题,所以觉得有必要站在一个“双修(残废)”者的角度,谈谈这个问题。
Java内存分配
在解释这个问题之前,我想简单的记录一下Java虚拟机对内存的分配管理。
网上有很多关于Java内存管理的讲解,但不知道为什么,大多数作者并没有系统的讲解,有些过于散碎。
我们先来看看这张图(我不会画图,画的太丑,各位受累受累了)。简单的说,Java运行时内存区域,就由上面几部分构成。青绿色标记的,是每个线程私有的内存区域,其他的为线程共享的内存区域。我们先简单的依次说明每个部分是用来存什么的,最后再用一个简单的例子,将各个部分结合起来简单介绍其内存分配的基本过程。
首先,程序计数器(pc)。这个东西对于很多开发者来说,再熟悉不过了,尽管不同领域的pc,具体用法上存在一些小小的差异,但总的来说,pc是用来记录程序运行到哪里了,下一步又该执行哪一步操作。pc占据的内存是线程级的,即随线程的创建而产生,随线程的销毁而销毁(被回收)。
其次JVM栈和本地方法栈。这两个栈在存储结构上,基本相同,以至于很多的JVM产商,将二者合而为一。JVM栈,顾名思义,是用来存储Java方法运行过程中使用的栈数据,本地方法栈就是用来存储本地方法执行过程中的栈数据。栈中存储的数据,是一种被称为“栈帧”的东西。栈帧主要包括:局部变量表和操作数栈。栈帧的入栈和出栈,分别意味着一个方法的执行与结束。
接着,我们来看看方法区。方法区主要是用来存类型数据的,与类型相关的东西,比如常量,静态变量,编译后的代码等,基本都存储在这一区域。而因为“无用类”的判断条件非常苛刻(有三点,第一,该类无可达对象,第二,该类的ClassLoader已被回收,第三,该类的Class对象无引用),这个区域存储的内容很难会被回收,所以你可能会在很多地方看到“永久代”一词,其实说的主要也就是这个方法区。方法区中,有个特殊的区域,被划分(逻辑划分,不一定为物理划分)出来,即“运行时常量池”。运行时常量池,保存着字面量,符号引用等。方法区是线程共享的,随JVM启动而创建,JVM退出而销毁。
最后,是这个堆。堆,在很多领域也有用到。在Java中,堆,是用来存储对象的相关内容,包括对象的对象头和实例数据(数组对象还有一个数组的长度)。不同的JVM实现,对象可能还包括类型指针(指向对象所属的类型信
