一. Java内存区域分布
Java在执行程序时会把管理的内存分成若干不同的数据区,接下来笔者将简单介绍:栈(Stack),堆(Heap),方法区等几个常用的内存区域.
1.程序计数器(PC)
一个处理器在一个时刻只能执行一个线程,java多线程是通过线程之间快速切换来实现的,所以线程直接需要一个内存来标记接下来需要调用哪一个线程.如:A线程执行,其中调用B线程的方法,那么等B执行完之后才返回继续调用A线程直到执行完毕.注意.每个线程的程序计数器是私有的,线程直接互不影响.
2.虚拟机栈(vm stack)
常说的栈内存,指的就是虚拟机栈,栈内存每个线程私有,不共享每个方法就是一个栈帧(Stack Frame),一个方法运行会将创建一个栈帧入栈(push),执行完就会将栈帧出栈(POP).
栈帧用于存储:局部变量表,操作数栈,动态链接,方法出口等.
局部变量表中存放八大基本数据类型和对象引用(reference)
3.本地方法栈(native stack)
本地方法栈是虚拟机程序运行依赖的C,C++的方法
4.堆(heap)
堆内存是存储对象实例的,所有线程都可以调用,所有是线程共享的,垃圾回收主要回收堆里的不用的对象.
堆内存可以分为:新生代和老年代 默认比例(新:老=1:2)
新生代又可以分为:eden区,from survivor区,to survivor区.例如第一次回收把eden区的和from survivor区的存活对象回收放到to survivor区,第二次回收把eden区的和to survivor区放到from区.(简;from survivor和to survivor区不停的交换,达到一定次数说明经常用此对象就放到老年代)
一个对象再堆中的内存布局:
每个对象分为四部分:markword,类型指针,实例数据,对齐(padding)
5.方法区(Method Area)
方法区存储:类信息,常量,静态变量等…所有线程都可以查看方法区的内容,所以线程直接共享
运行是常量池属于方法区的一部分,存储编译过程中产生的常量,符号引用,直接引用.(对象加载到classloader会经过解析阶段将符号引用转换为直接引用)
6.补充
java NIO引入了通道(channel),(缓冲区)buffer的新I/O方式,可以 直接调用Native方法操作内存空间