码迷,mamicode.com
首页 > 编程语言 > 详细

Java虚拟机

时间:2020-10-09 20:39:35      阅读:24      评论:0      收藏:0      [点我收藏+]

标签:二进制   算法   命令行启动   execution   java   weak   存储结构   加载   return   

Java虚拟机概念

  • 为何使用Java虚拟机

    1. 实现Java的跨平台特性
    2. 把目标代码编译成字节码
  • Java虚拟机的生命周期

    1. 程序开始执行时虚拟机才运行,程序结束时它就停止。每个Java程序会单独运行一个Java虚拟机。

      通过命令行启动java虚拟机:java xxxx(类名)

    2. Java虚拟机总是开始于一个固定格式的main()方法,程序执行时,必须给虚拟机指明这个包含有main()方法的类名。

      public static void main(String[] args)

  • Java虚拟机的体系结构

    1. Java虚拟机的规范中定义了一系列的子系统、内存区域、数据类型和使用指南。
    2. 每个java虚拟机都有一个类加载器子系统(class loader subsystem),负责加载程序中的类型(class和interface),并赋予唯一的名字。每个java虚拟机都有一个执行引擎(execution engine)负责执行被加载类中包含的指令。
  • Java虚拟机中使用的数据类型

    1. 原始数据类型(primitive types)

      包括“四类八种”,整型类、浮点数类、字符型、布尔型。

    2. 引用数据类型(reference types)

    注:

    1. java虚拟机中存在一个不能使用的原始数据类型----返回值类型(return value),这种类型被用来实现“finally classes”

    2. 引用类型可能被创建为:类类型、接口类型、数组类型。

Java虚拟机内存划分

如下图所示:

技术图片

  • 程序计数器

    JVM将这个计数看做是当前线程执行某条字节码的行数,根据计数器的值来选取需要执行的操作语句。

  • 虚拟机栈

    即进程说到的栈内存,java中每个方法从调用到执行的过程,对应一个栈帧在虚拟机栈中入栈到出栈的过程。

  • 本地方法栈

    用来执行本地方法,比如嵌入C/C++代码执行。

  • 堆是JVM中内存最大、线程共享的一块区域。唯一的目的是存储对象实例。垃圾回收器的主要回收区域。

  • 方法区

    JVM中内存共享的一块区域,用来存储类信息、常量、静态变量、class文件。垃圾回收器也会对该部分进行回收。

Java虚拟机类加载机制

虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型。

java语言里,类型的加载和连接过程是在程序的运行期间完成的。

  • 类的生命周期

    1. 加载loading

      通过一个类的全限定名来获取此类的二进制字节码,将该字节码所代表的的静态存储结构转换为方法区的运行时数据结构。在java中生成一个代表这个类的Class对象,作为方法区的这些数据的访问入口。

    2. 验证verification

      • 虚拟机规范
      • 文件格式验证
      • 元数据验证
      • 字节码验证
      • 符号引用验证
    3. 准备preparation

      类变量(用static修饰的类的变量)分配内存并设置初始值,这些内存将在方法区中进行分配。

    4. 解析resolution

      解析是在虚拟机中将常量池内的符号引用替换为直接引用的过程。

    5. 初始化initialization

      • clinit()方法:收集类中所有类变量的赋值和静态语句块
    6. 使用using

      • 类的主动引用
        1. 使用new、getstatic、putstatic、invokestatic方法
        2. 使用类的反射调用
        3. 父类初始化
        4. 虚拟机启动,初始化主类(包含main方法的那个类)
      • 类的被动引用
        1. 通过子类引用父类的静态字段,不会导致子类的初始化(对于静态字段,只有直接定义这个字段的类才会被初始化)
        2. 通过数组定义类引用类:ClassA[] array = new ClassA[10]
        3. c常量会在编译阶段调用类的常量池
    7. 卸载unloading

判断对象是否存活算法及对象引用

  • 垃圾回收

    当一个对象没有引用指向它时,这个对象就成为无用的内存(垃圾),就必须进行回收,以便用于后续其他对象的内存分配。

  • 引用计数算法

    Java语言没有选用引用计数算法来管理内存,最主要的一个原因是它很难解决对象之间相互循环引用的问题。

  • 可达性分析算法(根搜索算法)

    在主流的商用程序语言中(java和c#),都是可达性分析判断对象是否存活的。

    根搜索算法是从离散数学中的图论引入的,程序把所有的引用关系看做一张图,从一个节点GC ROOT开始,如果一个节点与GC ROOT之间没有引用链存在,则该节点视为垃圾回收的对象。

    在Java语言里,可以作为GC ROOT对象的包括如下几种:

    1. 虚拟机栈中引用的对象
    2. 方法区中的类静态属性引用的对象
    3. 方法区中的常量引用的对象
    4. 本地方法栈中JNI的引用的对象
  • 对象引用-强引用

    只要引用存在,垃圾回收期永远不会回收。

    Object obj = new Object()

  • 对象引用-软引用

    非必须引用,内存溢出之前进行回收

    Object obj = new Object();
    SoftReference<Object> sf = new SoftReference<object>(obj);
    obj=null;
    sf.get();
    

    软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。

  • 对象引用-弱引用

    在第二次垃圾回收时回收

    Object obj = new Object();
    WeakReference<Object> wf = new WeakReference<object>(obj);
    obj=null;
    wf.get();  //有时会返回null
    wf.isEnQueued();
    

    弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过isEnQueued()方法返回对象是否被垃圾回收器所回收

  • 对象引用-虚引用(幽灵/幻影引用)

    在垃圾回收时回收,无法通过引用取到对象值

    Object obj = new Object();
    PhantomReference<Object> wf = new PhantomReference<object>(obj);
    obj=null;
    wf.get();  //永远返回null
    wf.isEnQueued();
    

    虚引用主要用于检测对象是否已经从内存中删除

分代垃圾回收

在java代码中,java语言没有显式的提供分配内存和删除内存的方法。一些开发人员将引用对象设置为null或调用System.gc()来释放内存。

如果没有显式删除内存的话,垃圾回收期会去发现不需要(垃圾)的对象,然后删除它们,释放内存。

  • 年轻代和老年代

    年轻代:新创建的对象都存放在这里。minor GC

    老年代:没有变得不可达,存活下来的年轻代对象被复制到这里。major GC(或full GC)

  • 年轻代组成部分

技术图片

Java虚拟机

标签:二进制   算法   命令行启动   execution   java   weak   存储结构   加载   return   

原文地址:https://www.cnblogs.com/hunter-w/p/13783246.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!