JVM运行时线程共享区域

Java 堆

  1. Java堆是虚拟机所管理内存中最大的一块,被所有线程共享的一块内存区域,在Jvm启动时创建。 此内存区域的唯一目的:
    存放对象实例,几乎所有对象实例都是在这里分配内存。 根据Java虚拟机规范:
    所有对象的实例以及数组都是在这里(堆)上分配,但随着JIT的发展,并不是所有对象在堆上分配。

  2. Java堆是垃圾收集器管理额主要区域,因此也被称作是"GC堆"。
    1.从内存回收的角度看: 收集器大都采用分代收集算法,所以Java堆还可以细分为: 新生代和老年代:-> 再往下分有Eden,From Survivor,To Survivor等。
    2.从内分配的角度上看,Java堆还可能分出多个线程私有的分配缓冲区*(Thread Local Allocation Buffer TLAB)。进一步划分是为了更好的回收内存。

  3. 根据Java虚拟机规范,Java堆可以处于物理上不连续的内存空间中,只需要再逻辑上是连续的即可。和磁盘空间一样,可以实现成固定大小的,也可以是可扩展的,当前虚拟机大都是按照扩展方式来实现(-Xmx和-Xms控制)。如果在堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出OutOfMemoryError异常。

方法区

  1. 方法区(Method Area)与Java堆一样,是各线程共享区域,用于存储已经被虚拟机加载的类,常量,静态变量,即时编译器编译后的代码等数据。也称为Non-Heap(非堆)。

  2. 方法区也可以称之为"永久代",但其。并不等价。如HotSpot虚拟机,GC分代收集扩展至方法区,也可以说用永久代实现方法区,这样HotSpot垃圾收集器就可以像管理Java堆一样管理内存,省去了在方法区编写内存管理代码。对于其他JVM(如BEA JRockit,IBM J9)没有永久代。如何实现方法区属于虚拟机内部实现细节,不属于虚拟机约束规范。用永久代实现方法区不是一个很好得注意,会出现内存溢出得问题,永久代有-XX:MaxPermSize上限,J9和JRockit只要没有到达进程可用内存上限,如32位系统4GB,就不会出现问题)。也只有极少数方法。如String.intern()会有影响。

  3. 有的虚拟机已经放弃永久代,采用Native Memory实现方法区,JDK1.7得HotSpot已经把存放在永久代的字符串常量池移除。

  4. JVM虚拟机规范对方法区的限制非常宽松,除了像Java堆一样不需要连续内存和可以选择固定大小或者可扩展外,还可以不实现垃圾收集。并非数据进入了方法区就如永久代一样永久存在了。这一区域内存回收主要针对常量池的回收和类型的卸载,但其成绩并非令人满意,尤其对类型的卸载,条件很苛刻,但也是必要存在的。

方法区-运行时常量池

  1. 运行时常量池是方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,会在类加载后进入方法去的运行时常量池中存放。

  2. Jvm对Class文件的每一部分格式都有严格规定,每一个字节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可,装载,执行。但对于运行时常量池,规范没有做任何细节要求,不同厂商的虚拟机可以按照自己的需要实现这个内存区域。

  3. 一般来说,除了保存Class文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。
    运行时常量池对于Class文件常量池还有另外一个重要特征就是具备动态性,并不要求常量一定只有在编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间可能将新的常量放入池中,利用较多的便是String类的intern()方法。运行时常量池是方法区的异步方法,自然会收到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。

直接内存

  1. 直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但会被频繁的使用,也会导致OutOfMemoryError异常

  2. JDK1.4中新加了NIO(New
    Input/Output)类,引入了基于通道(Channel)与缓存区(Buffer)的I/O方式,可以使用Native函数库直接分配堆外内存,然后通过一个存储再Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。能在一些场景中提高性能,避免了在Java堆和Native堆中来回复制数据。

  3. 本机直接内存的分配不会受到Java堆大小的限制,但既然是内存,还是会受到本机总内存(RAM以及SWAP区或者分页文件)大小以及处理器寻址空间的限制。服务器管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略直接内存,使得个内存区域总和大于物理内存限制,而导致OutOfMemory异常。

你可能感兴趣的:(java,jvm,jdk)