zoukankan      html  css  js  c++  java
  • JVM基础

      最近学习了JVM,知道得越多,才知道自己越不足,现在进行总结一下哈。

      (1)什么是虚拟机?

        相信学习JAVA的人都知道因为虚拟机JVM的存在,才使得java程序可以跨平台,跨操作系统进行运行。首先在D盘新建一个test.java,代码如下:

    public class test {
        public static void main(String[]args) throws InterruptedException{
        Thread.sleep(10000000);
        }
    }

        打开cmd控制台,执行javac test.java进行编译,然后再执行java test,打开进程管理器,如下:

        

        启动eclipse,同样新建一个test类,内容如上,执行run as java application,查看进程,如下:

        

        java.exe,javaw.exe 就是java虚拟机了。java虚拟机相当于java类,而java虚拟机实例,相当于我们new一个java类得到的对象,不过java虚拟机不是通

    new这个关键字而是通过java.exe或者javaw.exe来启动一个虚拟机实例。

      (2)虚拟机的生命周期

        java虚拟机中有两种线程,一种是守护线程,典型的就是gc线程,一种是非守护线程。java虚拟机中,只要有非守护线程存在,虚拟机实例就不会退出,也就

    是说只有当程序中所有非守护线程执行结束,虚拟机的生命周期才会结束。下面写个简单的例子:

    package test;
    
    public class testDemo {
    
        public static void main(String []args) throws InterruptedException{
            new Thread(new Runnable() {
                public void run() {
                    for(int i=1;i<3;i++){
                        try {
                            Thread.sleep(i*100000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            
            for(int i=0;i<20;i++){
                System.out.print(i+",");
            }
        }
    }

        console 输出如下:

        

        当主线程执行完后,由于程序中开启的另外一条线程还没有执行完成,所以java虚拟机一直运行着。

      (3)虚拟机的基本结构

        

        (1)类加载子系统:负责从硬盘中加载Class信息,然后将类的信息存放在方法区中。例如,当ClassLoader启动的时候,首先到硬盘中test.class装载到jvm的方法区中,方法区中的这个字节码会被虚拟机执行new操作,然后在堆中生成一个test对象。

        (2)方法区:或称永久区,类似我们电脑中的硬盘,存放类的一些信息,类信息,字段信息,方法信息,指向对象的引用等等,新建一个类,你就知道方法区存放类的哪些信息了,如下:

    package test;
    
    import java.io.Serializable;
    
    //1.类信息
    public final class testDemo implements Serializable {
    
         private static final long serialVersionUID = 1L;
         
         //2.对象字段信息
         private String name;
         private int id;
         
         //4.常量池
         public final int CONST_INT=0;
         
         //5.类变量区
          public static String static_str="static_str";
          
         //3.方法信息
         public String add(){
             return "jvm";
         }
         
         public String getName() {
            return name;
         }
         public void setName(String name) {
            this.name = name;
         }
         public int getId() {
            return id;
         }
         public void setId(int id) {
            this.id = id;
         }
    
    }

         (3)java栈:每一个java线程都有一个私有的java栈,存放着局部变量以及java堆中对象的引用变量。

         (4)java堆:new出来的对象都存放在java堆中,堆空间是所有线程共享的。

         (5)垃圾回收系统:gc主要是对java堆,方法区,直接内存进行垃圾回收,释放内存。

         (6)直接内存:直接内存是在java堆外的、直接向系统申请的内存空间。通常访问直接内存的速度会优于java堆。因此,读写频繁的场合可能会考虑使用直接内存。由于直接内存在java堆外,因此它的大小不会直接受限于Xmx指定的最大堆大小,但是系统内存是有限的,java堆和直接内存的总和依然受限于操作系统能给出的最大内存。

        (7)pc寄存器:pc寄存器是用于存放下一条将要执行的指令的地址。

        (8)执行引擎:负责执行虚拟机的字节码。

      (4)java堆结构

        

        java堆整体分两个部分,即新生代和老年代。新生代主要存放新生对象,老年代主要存放时间比较久的对象,也就是多次GC后还存活的对象。新生代又可以分为eden(伊甸区)和幸存区(s0和s1)。

        对象刚创建的时候,一般都存放在eden区,除非对象特别大,直接存放在老年代。如果eden区的对象在经历过gc后还存活,则进入s0或s1区。s0和s1是两个大小,结构完全一样的内存空间,每次都知使用一个。在新生代区,垃圾回收机制一般使用的是复制算法。比如,当创建两个对象A,B后,首先进入eden区,在经历过gc后,存活的对象进入幸存区s0或s1,这里假设A,B都存活且进入了s0。下次进行gc后,假设A没有被引用了,B还存活,这时,复制算法,首先将s0中存活的对象,即B对象复制到幸存区s1,然后将s0清空。下次gc又将s1区中存活的对象复制到s0中,然后清空s1,以此类推。经过多次gc后还存活的话,则进入了老年代。

      参考文档:http://m.blog.csdn.net/article/details?id=8289363

  • 相关阅读:
    河北省重大技术需求征集七稿第二天
    河北省重大技术需求征集七稿第一天
    CNN网络架构演进
    C++学习-类域、友元、运算符重载、对象的生存期,可见域,作用域(2)
    C++学习-类域、友元、运算符重载、对象的生存期,可见域,作用域(1)
    C++学习-输入输出
    C++学习-new delete扩展
    C++学习-类和对象(2)
    C++学习-类和对象(1)
    C++学习-程序内存分配方式
  • 原文地址:https://www.cnblogs.com/gdpuzxs/p/6919270.html
Copyright © 2011-2022 走看看