JVM类的加载步骤,自己理解整理

du -h /home/appadmin/upload/ 查询指定目录下面内存使用的情况

一、序列化:

序列化的特点:

1:所有保存到磁盘上的对象都有序列化编号

2:当程序试图序列化一个对象时,程序检查该对象是否已经序列化过,

只有该对象从未(在本次虚拟机中)被序列化过,系统才会将该对象转换为字节序列并输出

3:如果对象已经被序列化过,程序将只是直接输出一个序列化编号,而不是再次进行重新序列化该对象

二、类的加载和jvm:

jvm启动加载所有的线程和类,当出现以下情况是将终止:

1:程序运行到最后正常结束

2:程序运行时使用了System.exit()或Runtime.getRuntime().exit()代码处程序结束

3:程序过程中遇到了未捕获到的异常或者错误而结束

4:程序所在的平台强制将诶输了JVM进程

开发者可以通过集成ClassLoader的基类来创建自己的类加载器

加载类的二进制数据的来源:

1:本地文件加载class文件,这是前面绝大部分实力程序的加载方式

2:从jar加载class文件,这种方式也是很常见的,前面介绍的JDBC编程时

用到的数据驱动类就放在JAR文件中,JVM可以从jar文件中直接加载class文件

3:通过网络加载class文件

4:把一个java源文件动态编译,并执行加载

三、类的加载过程:

类的连接的准备的目的主要是类的验证目的是确定java类二进制数据的正确性,

也因为java虚拟机不知道.class文件是如何被创建的,有可能是正常创建,也有可能是黑客特质破坏虚拟机的所以要有验证环节,提高程序的健壮性

对于Java程序中每个正在运行的线程,都有一个PC寄存器保存着当前执行的指令地址

java虚拟器可以一次编译在不同的平台操作系统上运行,运行时把字节码转换为不同的机器指令执行,一次编译到处运行

1、类的声明周期分为五个步骤:

1.1:加载

1.1.1:创建class文件,放到内存中

1.1.2:(1)类的加载器分为系统自带的加载器:1、包括启动类加载器,2、扩展类加载器,和3、系统类加载器

  (2) 用户自定义加载器:ClassLoader类的子类,用户可以通过实现该类来定制类的加载方式

1.2.3:

1.2:连接

1.2.1:验证

    1.2.1.1:检查文件的格式,确保遵循java的固定格式

1.2.1.2:确定java的语意是否正确,验证final是否有子类,final修饰的方法是否被重写,

注:final修改变量不能修改,修饰方法不能重写,修饰类不能被继承

1.2.1.3:确保字节码流可以被java虚拟机正确的执行,它是由操作码的单字节指令组成的序列,

每一个操作码都跟着一个或多个操作数,java虚拟机会验证该操作数是否合法

1.2.1.4:二进制兼容验证:确保类与类之间引用的协调性;如A类中a方法引用B类中b方法,虚拟机会验证A类时会检查方法区内是否有B类的b方法,

如果不存在或不兼容时,会抛出NoSuchMethodError异常

1.2.2:准备

1.2.2.1:为类的静态变量分配内存空间,并将其赋予默认值,注意是初始值 如static int类型初始值为0

1.2.3:解析

1.2.3.1:将类中的符号引用转换为直接引用,主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符类符号引用进行。

如在A类中a方法中引用了B类中的b方法,将b方法放入A类中

1.3:初始化

1.3.1:类的初始化步骤:步骤2中父类含有父类则进行123的顺序依次再次执行

1.3.1.1:假如这个类没有被加载或者连接,则程序先加载并且连接该类

1.3.1.2:假如该类的直接父类还没有初始化,则先初始化其直接父类

1.3.1.3:假如类中有初始化语句,则系统依次执行这些初始化语句

1.3.2:类初始化的方式:类的实例化主要对变量、静态代码块和私有构造的初始化,使用final修饰,调用时不会进行初始直接赋值引用

1.3.2.1:Student stu = new Student();new对象的方式

1.3.2.2:反射的方式:Class.forName("XXX").newInstance

1.3.2.3:使用java.lang.relect.Constructor的方式,Constructor<Student> constructor = Student.class.getConstructor(Integer.class);

Student stu3 = constructor.newInstance(123);使用该方式可以获取参数的私有构造

1.3.2.4:克隆的方式,使用java.lang.relect.Constructor的方式获取再进行调用。clone方法

1.3.3.5:通过反序列化本地实体类的文件

1.4:使用

1.4.1:类的加载器:

1.4.1.1:Bootstrap ClassLoader:根加载器,加载java运行的核心类,在jvm启动时进行加载,存放于<JAVA_HOME>\lib下面的核心类都由它加载

1.4.1.2:Extendsion ClassLoader:扩展类加载器加载<JAVA_HOME>\lib\ext下面核心的类文件,对外扩展使用可以在里面添加自己常使用的jar文件

1.4.1.3:Application ClassLoader:应用程序类加载器,加载CLASSPATH下面的jar,一般我们编写的java类都是由这个类加载器加载,这个类加载器是CLassLoader中的getSystemClassLoader()方法的返回值,所以也称为系统类加载器.一般情况下这就是系统默认的类加载器.

除此之外,我们还可以加入自己定义的类加载器,以满足特殊的需求,需要继承java.lang.ClassLoader类.没有指定用户自己编写的类加载器作为父类加载器

1.4.2:双亲委派原型:所有的类加载器请求加载类的时候,类不会直接被加载,而是去请求父类进行加载,只有父类无法加载时才会让子类进行加载,比如java.langObject,

它存放在\jre\lib\rt.jar中,它是所有java类的父类,因此无论哪个类加载都要加载这个类,把所有的类汇总到顶层,进行统一的加载

1.5:卸载

四:jvm的内部分配

1:类加载子系统负责从文件系统或者网络中加载Class信息,存放于方法区,主要存放类的信息,方法区中可能还会存放运行时常量池信息---方法区的使用

2:jvm启动时建立堆区,java实例存放于堆区,堆空间是所有线程共享的,这是一块与java应用密切相关的内存空间--堆区

  2.1:java堆是和应用程序关系最为密切的内存空间,几乎所有的对象都存放在堆上

  2.2:根据java回收机制的不同,java堆有可能拥有不同的结构。最为常见的一种构成是将整个java堆分为新生代和老年代。其中新生代存放新生对象或者年龄不大的对象,

  老年代则存放老年对象。新生代有可能分为eden区、s0区、s1区,s0区和s1区也被称为from和to区

  2.3:

3:java的NIO库允许java程序使用直接内存。直接内存是在java堆外的、直接向系统申请的内存空间,访问速度快,内存受限于Xmx和机器的运行内存--直接内存区

4:垃圾回收系统是java虚拟机的重要组成部分,垃圾回收器可以对方法区、java堆和直接内存进行回收。其中,java堆是垃圾收集器的工作重点

5:每一个java虚拟机线程都有一个私有的java栈,一个线程的java栈在线程创建的时候被创建,java栈中保存着帧信息,

java栈中保存着局部变量、方法参数,同时和java方法的调用、返回密切相关。--栈区

  5.1:栈执行压栈执行,先进后出的原则,它保存着当前函数的局部变量、中间计算结果等数据。

  5.2:递归函数的调用使用参数的数量和函数的调用次数影响栈内存的使用的大小,相同的函数调用的次数参数较多的方法调用会更快消耗

  栈的内存,系统会抛出StackOverflowError栈溢出错误

  5.3:栈帧中局部变量表中的槽位是可以重用的,如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变量就很有可能会

  复用过期局部变量的槽位,从而达到节省资源的目的。如public class TestReuse {

  public static void localvar1(){

    int a=0;

    System.out.println(a);

    int b=0;

  }

  public static void localvar2(){

    {

      int a=0;

      System.out.println(a);

    }

    int b=0;

  }

}localvar2中的b变量复用了a的槽位

五、垃圾的回收机制

1、对新生代的对象的收集称为minor GC;

2、对旧生代的对象的收集称为Full GC;

3、程序中主动调用System.gc()强制执行的GC为Full GC。

4、不同的对象引用类型, GC会采用不同的方法进行回收,JVM对象的引用分为了四种类型:

(1)强引用:默认情况下,对象采用的均为强引用(这个对象的实例没有其他对象引用,GC时才会被回收)

(2)软引用:软引用是Java中提供的一种比较适合于缓存场景的应用(只有在内存不够用的情况下才会被GC)

(3)弱引用:在GC时一定会被GC回收

(4)虚引用:由于虚引用只是用来得知对象是否被GC

六、this方法的使用

1、构造器中引用该构造器正在初始化的对象

2、在方法中引用调用该方法的对象

七、面向对象:注(rt.grow().grow(),连续调用同一个方法直接.方法名)

1:面向对象的三大特征:

1.1:封装:java提供了private、protect和public等访问修饰符来进行良好的封装,修饰符可以完全省

1.1.1:封装的意义:(把该隐藏的隐藏,把该暴露的暴露)

1.1.1.1:隐藏类的实现细节

1.1.1.2:限制对成员变量不合理的访问

1.1.1.3:检查数据的完整性和准确性

1.1.1.4:便于修改,不用全局检索修改

1.2:继承:extend关键字进行继承父类,使用父类的成员变量和方法(类中一般包括构造器、成员变量和方法)

1.2.1:继承的规则:

1.2.1.1:当子类的方法名和父类额方法名相同时现象为重写或者覆盖

1.2.1.2方法重写遵循“两同两小一大的原则”的原则,两同指的是方法名相同和形参列表相同,两小指的是子类返回值类型应比父类方法返回值类型更小或者相同

子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或者相等,一大指的是子类方法的访问权限比父类的访问权限更大或者相等

1.3:多态:构造器用于对实例进行初始化操作,构造器支持重载(类被加载,提供默认的构造器,否则类无法被实例化,构造器返回值和隐式的)

2:

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 15,874评论 3 83
  • 第二部分 自动内存管理机制 第二章 java内存异常与内存溢出异常 运行数据区域 程序计数器:当前线程所执行的字节...
    小明oh阅读 4,908评论 0 2
  • 《深入理解Java虚拟机》笔记_第一遍 先取看完这本书(JVM)后必须掌握的部分。 第一部分 走近 Java 从传...
    xiaogmail阅读 10,610评论 1 34
  • 工作之余,想总结一下JVM相关知识。 Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的...
    Huang远阅读 3,790评论 0 2
  • 介绍JVM中7个区域,然后把每个区域可能造成内存的溢出的情况说明 程序计数器:看做当前线程所执行的字节码行号指示器...
    jemmm阅读 6,648评论 0 9