JVM虚拟机

Java内存区域

1、程序计数器

计数器记录了当前线程执行到了哪一行的字节码指令,每条线程都拥有一个独立的程序计数器,线程切换中,让线程记得下一条要执行的指令,感觉类似指针。

2、Java虚拟机栈

Java虚拟机栈也是线程私有的,栈主要存储的内容是方法执行时的局部变量表,包括各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(指向一个对象地址的指针)和returnAddress类型(指向一条字节码指令的地址)。

每个线程都拥有一个虚拟机栈,线程中每个方法执行时都会在栈中创建一个栈帧,方法每递归一次,就新建一个栈帧,依此类推。

(1)线程运行时的栈帧总得大小超过虚拟机限制的大小,会抛出StackOverflow异常,这一点通常发生在递归运行时;

(2)虚拟机栈设置为可以动态扩展,并且在扩展时无法申请到足够内存,则会抛出OutOfMemory异常。

3、本地方法栈

和虚拟机栈是十分相似的,主要都是存储着方法执行的局部变量的信息,地方法栈是为虚拟机使用到的本地Native方法服务。

4、Java堆

(1)Java堆是Java虚拟机内存中最大的一块,是被所有线程共享的一块内存区域。

(2)存放Java对象实例,因此Java堆也是垃圾收集的主要区域。

(3)堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可

(4)当堆没有内存完成实例分配,且无法继续扩展时,就会抛出OutOfMemory异常,可以通过-Xmx和-Xms参数来控制堆的大小。

5、方法区

方法区用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据,也是各个线程共享的内存区域。

6、直接内存

直接内存并不是虚拟机运行时数据区的一部分,但是Java可以对这部分的内存进行使用。如果直接内存使用过多,超过了机器的物理内存限制,就会导致OutOfMemory异常。

 

堆溢出

    

public class TestHeap {
  public static void main(String [] args){
    List<String> list=new ArrayList<String>();

    while(true){
      list.add("1");
    }
   }
}

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2245)
at java.util.Arrays.copyOf(Arrays.java:2219)
at java.util.ArrayList.grow(ArrayList.java:242)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
at java.util.ArrayList.add(ArrayList.java:440)
at test_Java.TestHeap.main(TestHeap.java:11)

 

栈溢出

public class TestStack {
  private int i=1;

  public void stackleak(){
    i++;
    stackleak();
  }
  public static void main(String[] args) {
    TestStack t=new TestStack();
    try{
        t.stackleak();
      }catch(Throwable e){
        System.out.println("length="+t.i);
          throw e;
      }

    }
  }

Exception in thread "main" java.lang.StackOverflowError

 

posted @ 2018-07-26 00:47  闲花落尽  阅读(40)  评论(0)    收藏  举报