• JVM笔记(二)JVM基本结构


    JVM基本结构 

    一、运行时内存区域

          java虚拟机所管理的内存将会包括以下几个运行时内存区域。

          

          1.程序计数器

            Program Counter Register:可以看作当前线程(线程私有)所执行的字节码行号指示器。

          2.Java虚拟机栈

            Java Virtual Machine Stacks:也是线程私有的,描述了Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧用于存储---局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完毕的过程,都对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

           局部变量表:存放了方法内部编译期可知的各种基本数据类型,对象引用类型。

           

     

           在虚拟机规范中,虚拟机栈规定了两种异常情况:

           1)StackOverflowError:线程请求栈的深度大于虚拟机所允许的深度。

           2)OutOfMemoryError:虚拟机动态时,无法申请到足够的内存。

          3.本地方法栈

            与虚拟机栈的方法栈作用相似,只是本地方法栈为虚拟机使用的Native方法服务。可抛出虚拟机栈相同的异常。

          4.Java堆

            Java Heap:被所有线程共享的一块内存区域,在虚拟机启动时创建。用于存放对象实例和数组。是Java垃圾收集器所管理的主要区域,因此也被称为“GC堆”。Java虚拟机规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。 

           可以抛出OutOfMemory异常。

         5.方法区

           Method Area:线程共享区域,用于存放已经被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等信息。虚拟机规范把方法区描述为堆的一个逻辑部分。

              6.运行时常量池

             Runtime Constant Pool:方法区的一部分,Class文件中的常量池(用于存放编译期生成的各种字面量和符号引用)中的内容,在类加载后进入方法区中的常量池存放(也可将运行期间新产生的常量放入池中)。

         7.直接内存       

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

    二、JVM内存模型

     1 public class VolatileStopThread extends Thread{
     2     private volatile boolean stop=false;
     3     public void stopIt(){
     4         stop=true;
     5     }
     6 
     7     @Override
     8     public void run(){
     9         int i=0;
    10         while (!stop){
    11             i++;
    12         }
    13         System.out.println("Stoped running");
    14     }
    15 }
    16 
    17 
    18 public class MainClass {
    19 
    20     public static void main(String[] args) {
    21         //没有volatile -server运行无法停止
    22         //虽然很多情况下volatile性能比锁好但不能代替锁
    23         //因为volatile不是线程安全的
    24         VolatileStopThread v=new VolatileStopThread();
    25         v.start();
    26         try {
    27             Thread.sleep(1000);
    28             v.stopIt();
    29             Thread.sleep(1000);
    30         } catch (InterruptedException e) {
    31             e.printStackTrace();
    32         }
    33     }
    34 }

     

    线程内有序意思是:在本线程内的变量什么的编译器是会考虑语义的。

     

    Simple is important!
  • 相关阅读:
    获取设备唯一标识 uuid(采用第三方库SSKeychain)
    基于定时器的动画和性能调优
    获取设备的唯一标识uuid
    获取网络状态ios(2G、3G、4G、Wifi)
    equals 为什么要把常量写在前面?
    svn提交更新代码提示Please execute the 'Cleanup' command 的解决办法
    C# 一次循环获取树的两种方法
    递归拼装无限层级菜单树
    mysql错误:Column count doesn't match value count at row 1解决办法
    IDEA 解决Number objects are compared using '==', not 'equals()' 警告
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/7138403.html
Copyright © 2020-2023  润新知