一般作为Java程序员在面试的时候一般会问的大多就是Java内存区域、虚拟机垃圾算法、虚拟垃圾收集器、JVM内存管理这些问题了,对此我参照了一些网上的面试题做出了一些总结
介绍下Java内存区域(运行时数据区)
- 程序计数器:线程私有,因为在线程切换后,要能够恢复到正确的位置,所以是私有的,工作的时候通过改变程序计数器的值来选取下一条指令进行执行
- Java虚拟机栈:同样线程私有,生命周期等同于线程,描述的是java的运行时内存模型
- 本地方法栈:为虚拟机用到的native方法服务
- 堆:Java虚拟机所管理的内存中最大的一块,Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存
- 方法区:方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据
- 运行时常量池:运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有常量池信息
- 直接内存:直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致OutOfMemoryError异常出现
对象的访问定位的两种方式。
- 使用句柄
- 如果使用句柄的话,那么Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息
- 直接指针
- 如果使用直接指针访问,那么Java堆对像的布局中就必须考虑如何防止访问类型数据的相关信息,reference中存储的直接就是对象的地址
这两种对象访问方式各有优势。使用句柄来访问的最大好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。使用直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销