zoukankan      html  css  js  c++  java
  • JVM 学习笔记(一)

    JVM  ----Java  Virtual Machine   (熟称:JAVA虚拟机),JVM 在执行JAVA程序的过程中将内容划分为若干个区域,其有各自的用途和管理机制。如下图:

     

    1.  程序计算器(Program Counter Register)  --  是当前线程所执行字节码的行号指示器,通过改变其值来实现执行不同的代码指令。内存占用小,线程私有,支持多线程处理(多线程时,每个线程有一个独立程序计算器,已达到各自互不影响), 也正是由于这些特点,该区域是JVM规范中唯一没有规定任何OutOfMemoryError的区域。

    2.  JAVA 虚拟机栈(JVM Stack) 

        也是线程私有,和线程有相同的生命周期,是JAVA方法执行的内存模型, 即:每个方法执行时,都会同时创建一个Stack Frame(栈帧)用于存储局部变量(8种基本数据类型、对象引用类型)、操作数栈、动态链接、方法出口信息。方法调用到执行完成的过程也是Stack Frame栈帧出、入JVM Stack的过程.

        在JVM规范中,规定了两种内存异常:

        一是:线程请求的栈深度超过了栈允许的最大深度,将抛出:StackOverflowError 异常。

        二是:当JAVA虚拟机动态扩展时,无法申请到足够的内存时,将抛出:OutOfMemoryError异常。

         以下样例属于第一种情形:

     1 /**
     2 *  VM Args:  -Xss128K
     3 *  @author  yql
     4 *
     5 */
     6 public class JavaVMStackSOF {
     7     
     8      private int stackLength = 1;
     9      
    10      public void stackLeak(){
    11           stackLength ++;
    12           stackLeak();
    13      }
    14      
    15      public static void main(String[] arg) throws Throwable{
    16      
    17         JavaVMStackSOF oom = new JavaVMStackSOF(); 
    18         try{
    19           oom.stackLeak();
    20         }catch(Throwable e ){
    21             System.out.println("Stack length:"+ oom.stackLength); 
    22             throw e;
    23         }
    24      }
    25 }

     运行结果:

    Stack length:7907

    Exception in thread "main" java.lang.StackOverflowError

           at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)

           at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)

           at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)

           ... (省略相同栈信息)

    以下属于第二种情形:(注意!!!:  在运行以下样例前,请保持所有工作,可能导致操作系统假死。)

     1 /**
     2 *  VM Args:  -Xss2M
     3 *  @author  yql
     4 *
     5 */
     6 import java.lang.*;
     7 public class JavaVMStackOOM {
     8      private void dontStop(){
     9         while(true){        
    10         }
    11      }     
    12     public void stackLeakByThread(){
    13            while(true){           
    14              Thread  thread = new Thread(new Runnable(){
    15                    @Override
    16                    public void run(){
    17                       dontStop();
    18                    }             
    19                 });           
    20                thread.start();
    21            }     
    22     }     
    23      public static void main(String[] arg) throws Throwable{
    24      
    25         JavaVMStackOOM oom = new JavaVMStackOOM(); 
    26         oom.stackLeakByThread();
    27      }
    28 }


    运行结果为:

    Exception in thread "main" java.lang.OutofMemoryError: unable to create new native thread. 

     

    3.  本地方法栈(Native Method Stack)

        与JVM stack 相似,JVM stack 为虚拟机执行JAVA方法服务,而Native Method Stack 是为虚拟机执行本地方法服务。有的虚拟机对两者没有区分,合二为一。

       同样会存在两种异常: StackOverflowError   和  OutOfMemoryError  异常.   (样例如第2点中)

    4.   JAVA 堆(Heap)

     Heap 是java内存管理中最大的一块内存区域,被所有线程共享,用于存放对象实例,几乎所有的对象实例和数组都在此分配。

     在JVM规范中规定,JAVA堆可以物理不联系,只要逻辑空间联系即可。这样,当堆Heap无法完成再扩展时,将会抛出:OutOfMemoryError异常。

     所以,不断的创建对象,就会导致内存溢出.

     1 /**
     2 *  VM Args:  -Xms20m  -Xmx20m  -XX:+HeapDumpOnOutOfMemoryError
     3 *  @author  yql
     4 *
     5 */
     6 import java.util.*;
     7 public class HeapOOM {
     8     
     9      static class OOMObject{
    10      }
    11      
    12      public static void main(String[] arg){
    13      
    14         List<OOMObject>  list = new ArrayList<OOMObject>();
    15         
    16         while(true){
    17             list.add(new  OOMObject());
    18         }
    19      }
    20 }

      运行结果为:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
            at java.util.Arrays.copyOf(Unknown Source)
            at java.util.Arrays.copyOf(Unknown Source)
            at java.util.ArrayList.grow(Unknown Source)
            at java.util.ArrayList.ensureExplicitCapacity(Unknown Source)
            at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
            at java.util.ArrayList.add(Unknown Source)
            at HeapOOM.main(HeapOOM.java:17)

    5. 方法区(Method Area)

     方法区也是多线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译的代码数据。(JVM规范把方法区描述为堆的一个逻辑区域)

    方法区在无法满足内存分配时,将抛出OutOfMemoryError 异常。

    6.  运行时常量池(Runtime Constant Pool )

    运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池。

     1 /**
     2 *  VM Args:  -Xss2M
     3 *  @author  yql
     4 *
     5 */
     6 import java.util.*;
     7 public class RuntimeConstantPoolOOM {
     8      public static void main(String[] arg) throws Throwable{
     9         //使用List 保持常量池引用, 避免Full GC回收常量行为
    10         List<String> list = new ArrayList<String>(); 
    11         long  i= 0l;
    12         while(true){
    13           list.add(String.valueOf(i++).intern());
    14         }
    15      }
    16 }

    运行结果:

    Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

    at java.lang.String.intern(Native Method)

    at RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java 13)

      ....

    7. 直接内存(Direct Memory)

       本机内存分配不受JAVA 虚拟机(堆,栈等)的影响,但是受机器内存的影响,当各区域内存总和大于物理内存时,导致动态扩展内存出现:OutOfMemoryError异常。

    对象访问

      对象访问主要有两种方式:

    一种是,通过句柄访问对象;(优点在于:reference 中存储的是稳定的句柄地址,在对象被移动时,只改变句柄中实例数据指针,而reference本身不变)

    一种是,通过直接指针访问对象。(优点在于:速度更快,节省了一次指针定位时间)

  • 相关阅读:
    python3 进程间的通信(管道)Pipe
    python3 进程间的通信(队列)Queue
    python3 队列的简单用法Queue
    python3 进程锁Lock(模拟抢票)
    python3 守护进程daemon
    python3 僵尸进程
    python3 process中的name和pid
    python3 Process中的terminate和is_alive
    python3 通过多进程来实现一下同时和多个客户端进行连接通信
    python3 进程之间数据是隔离的
  • 原文地址:https://www.cnblogs.com/dragonflyyi/p/3709835.html
Copyright © 2011-2022 走看看