jvm(二):内存管理

    jvm内存区域总体分为5大块:方法区,java堆,虚拟机栈,本地方法栈,程序计数器,按照线程来分的话又分为线程共享区和线程独占区

   

   程序计数器:

   a、程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器

   b、此区域是唯一一个在java虚拟机规范中没有任何outofmemoryerror情况的区域

   c、如果线程执行的是java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果正在执行的是native方法(即本地方法栈服务的方法),这个计数器的值为undefined

   

   本地方法栈:

   a、本地方法栈为虚拟机执行native方法服务(虚拟机栈为虚拟机执行java方法服务)

   虚拟机栈:

   a、虚拟机栈描述的是java方法执行的动态内存模型

   b、栈帧,每个方法执行都会创建一个栈帧,伴随着方法从创建到执行完成,用于存储局部变量表(存放编译期可知的各种基本数据类型,引用类型,returnaddress类型,局部变量表的内存空间在编译期间完成分配,当进入一个方法,这个方法需要在帧分配多少内存是固定的,在方法运行期间不会改变局部变量表的大小),操作数栈,动态链接,方法出口等。

   c、可能出现StackOverflowError、OutOfMemory等异常

   java堆:

   a、存放对象实例

   b、垃圾收集器管理的主要区域

   c、堆被划分为两个不同的区域:新生代、老年代,新生代又被划分为三个区域:Eden、From Survivor、To Survivor

   d、堆大小可通过参数-Xms、-Xmx来指定

   e、会抛出OutOfMemory异常

   方法区:

   a、存储运行时常量池,已被虚拟机加载的类信息(类的版本,字段,方法,接口),常量(储存编译器生成的各种字面量和符号引用),静态变量、即时编译器编译后的代码等数据。

   b、方法区中很少进行垃圾回收,但是会执行垃圾回收,回收效率比较低,如对常量池的回收,对象类型的卸载等。

   c、会抛出异常OutOfMemoryError

   注意:

   如果Strng s1 = "abc"   String s2 ="abc"  s1==s2 输出为true

   因为,定义s1的时候,在堆中创建对象,并记录在方法区的运行时常量池的StringTable表中,再定义s2的时候发现StringTable中已经记录了这个对象,就不在堆中创建新的对象了,s2会指向第一个abc,而不是图中的第二个

   如果String s3 =new String("abc") ,则是s1==s3为false 直接在堆中开辟一块空间,而不再去考虑常量池的问题。如果,s1==s3.intern() 则返回为true,intern()方法会将s3的“abc”移动到运行时常量池中去(即产生一个运行时常量),但常量池中已经有“abc”所以相等。

   注意,还有直接内存(主要是nio使用)的存在,其不受虚拟机内存的制约,但是受到物理内存的制约。

原文地址:https://www.cnblogs.com/sbrn/p/8927642.html