JVM上不只能运行java程序,scala等其他语言也可以在jvm上运行,只要能生成jvm上可以理解的字节码文件就行。
在cmd中输入jconsole可以出现控制台
jvisualvm也是一种监控工具
jmap命令行工具

类加载
在java代码中,类型的加载、连接与初始化过程都是在程序运行期间完成的
什么是类型 ?定义的class\interface\枚举,并不是对象
类型的加载就是将类型所在的class文件/字节码文件从磁盘上加载到内存里面
连接:将类与类之间的关系处理好,对于字节码的处理验证校验都是在加载连接上完成的。
字节码文件可以被人为操纵,存在错误的可能,需要校验
初始化:对于静态变量进行赋值
提供了更大的灵活性,增加了更多的可能性

类加载器:每个类型都是由类加载器加载到内存当中的
在下面几种情况,java虚拟机将结束生命周期
1.执行System.exit();
2.程序正常执行结束
3.程序在执行过程中遇到了异常或错误而异常终止
4.由于操作系统出现错误而导致java虚拟机进程终止

类的加载:查找并加载类的二进制数据,class文件,就是把类的class文件加载到内存里
连接:

  • 验证:确保被加载类的正确性(class文件是符合JVM规范的)
  • 准备:为类的静态变量分配内存,并将其初始化为默认值(false,0)
  • 解析:把类中的符号引用转换为直接引用

初始化:为类的静态变量分配正确的初始值
类的使用与卸载
类的卸载是与类的加载相对应的

符号引用和直接引用:符号引用与虚拟机的内存布局无关,引用的目标并不一定加载到内存中。在Java中,一个java类将会编译成一个class文件。在编译时,java类并不知道所引用的类的实际地址,因此只能使用符号引用来代替。比如org.simple.People类引用了org.simple.Language类,在编译时People类并不知道Language类的实际内存地址,因此只能使用符号org.simple.Language(假设是这个,当然实际中是由类似于CONSTANT_Class_info的常量来表示的)来表示Language类的地址。各种虚拟机实现的内存布局可能有所不同,但是它们能接受的符号引用都是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
直接引用可以是
(1)直接指向目标的指针(比如,指向“类型”【Class对象】、类变量、类方法的直接引用可能是指向方法区的指针)
(2)相对偏移量(比如,指向实例变量、实例方法的直接引用都是偏移量)
(3)一个能间接定位到目标的句柄
直接引用是和虚拟机的布局相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经被加载入内存中了。

java程序对类的使用方式可分为两种:
1.主动使用
2.被动使用
所有的java虚拟机实现必须在每个类或接口被java程序首次主动使用时才初始化他们

主动使用(7种):

  • 创建类的实例
  • 访问某个类或接口的静态变量,或者对该静态变量赋值
  • 调用类的静态方法
  • 反射(如Class.forName(“com.test.Test”))
  • 初始化一个类的子类。当我初始化child类时,也会对parent类进行初始化
  • java虚拟机启动时被表明为启动类的类,即包含main方法的类
  • JDK1.7开始提供的动态语言支持。

    除了上面七种情况,其他使用java类的方式都被看作是对类的被动使用,都不会导致类的初始化



静态代码块在程序初始化的时候会被执行的


mychild1没有被初始化,但是有没有被加载呢,使用-XX:+TraceClassLoading,用于追踪类的加载信息并打印出来。打印出来发现,虽然没有被初始化,但是被加载的

对于静态字段来说,只有直接定义了该字段的类才会被初始化。
初始化一个类的子类时,父类也会被初始化。
在一个类初始化时,要求其父类全部都已经初始化完毕了

-XX:+,表示开启option选项
-XX:+,表示关闭OPTION选项
-XX:=,表示将option的值赋为Value
下面一个例子,加有final关键字 的常量

//常量在编译阶段会存入到调用这个常量的方法所在的类的常量池当中,
//本质上,调用类MyTest1并没有直接引用到定义常量的类MyParent,因此不会触发定义常量的类Myparent的初始化
//这里指的是将常量存放到MyTest1的常量池中,之后MyTest1与MyParent就没有关系了
//甚至可以将out文件夹下的MyParent.class文件删除

反编译MyTest1.class

E:\java_web_dev\kmoon\out\production\classes>javap -c com.ipoc345.kmoon.MyTest1
Compiled from "MyTest1.java"
public class com.ipoc345.kmoon.MyTest1 {public com.ipoc345.kmoon.MyTest1();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #4                  // String hello world5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: return
}

助记符:
ldc表示将int 、float或是String类型的常量值从常量池中推送至栈顶
bipush表示将单字节的(-128~127)的常量值推送到栈顶
public static final short s = 7;
sipush表示将一个短整型常量值-32768~32767推送至栈顶
public static final int s = 128;
iconst_1表示将int类型1推送至栈顶(iconst_m1~iconst_5,(-1——5))


所以在编译器是无法确定值的

Part8.

当一个常量的值并非编译期间可以确定的时候,那么其值就不会被放到调用类的常量池中,这时候在程序运行中,会主动使用这个常量所在的类,显然会导致这个类被初始化

实例化一个类

创建数组,并不会初始化类


对于数组实例,其类型是JVM在运行期动态生成的,表示为class[Lcom.kmoonwang.mywenda.Myparent3
这种形式动态生成的类型,其父类型是Object
助记符:
anewarray:创建一个引用类型的(如类、接口、数组)的数组,并将其引用值压入栈顶
newarray:创建一个原始类型(如int、char、float、double等)的数组,并将其引用值压入栈顶

接口中的域默认是static final的,那么当调用这个域的时候就和类一样不用初始化


调整一下位置结果就变了,这是为什么呢?
下面进行详细分析

调用静态方法是主动使用的一种情况

  1. 首先进行准备阶段
    给变量赋予默认值,counter1为0,singleton为null,counter2为0
  2. 按照顺序进行变量初始化
    counter1由于没有赋值,所以为默认值0
    singleton进行初始化,counter1 = 1;counter2 = 1;
    counter2进行初始化,counter2 = 0;
    初始化是自上而下的

类加载的顺序


Class对象是整个反射的入口

类是由类加载器来加载的


前面学到过所有的java虚拟机实现必须在每个类或接口被java程序首次主动使用时才初始化他们
但是一个类没有被初始化,并不代表它没有被加载










感觉这个说的有点问题,其实接口和类的本质是一样的,因为接口所有的变量都是static final的,所以相当于类中的一种特殊情况。就把接口考虑成变量定义为static final的类就行了







根据双亲委托机制,根加载器加载不了的使用扩展类加载器,扩展类加载器加载不了的使用系统类加载器,系统类加载不了就抛异常了。看起来很像继承关系,其实是包含关系。系统包含了扩展,扩展包含了根



当把class换成interface,把myparent5.class和child.class删掉再运行都不会报错

当interface的常量是编译期间不能确定的时候,那么就会加载类,如果能够确定就放到JVMlearning类的常量池当中
‘下面模拟,当一个类初始化的时候,它的接口不会初始化

子接口的初始化并不会导致父接口进行初始化



想要用loader1加载类,loader1先向上查看自己的父亲加载器-系统类加载器,系统类加载器还有父亲扩展类加载器,扩展类加载器还有根类加载器,然后从根类加载器对类进行加载,加载不成功就用扩展类加载器,不然就用系统类加载器。系统类加载器可以加载成功了。在上述过程中,有一个加载器加载成功就类加载完成了。




String类是由根加载器进行加载的,返回的Null代表根加载器

C类是由系统(应用)类加载器来加载的


MyTest10 static block
----------
Parent2 static block
----------
3
----------
Child 2 static block
4

parent3 static block
3
do something


分别把类加载器打印出来

深入理解JVM学习(b站 张龙视频 P1-P14)相关推荐

  1. 深入理解JVM虚拟机(文末有视频讲解)

    什么是JVM虚拟机 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实 ...

  2. 【JVM】最全笔记(黑马+尚硅谷+张龙整合笔记)

    本身整合了如下视频的笔记,并进行了整理:尚硅谷周阳.张龙.黑马程序员 黑马ppt非常好:https://download.csdn.net/download/hancoder/12834607 本文及 ...

  3. 1、张龙netty学习 第一个netty服务端

    张龙netty学习 第一个netty服务端 public class TestServer {public static void main(String[] args) throws Excepti ...

  4. JVM原理和调优的理解和学习

    JVM原理和调优的理解和学习 一.详解JVM内存模型 二.JVM中一次完整的GC流程是怎样的 三.GC垃圾回收的算法有哪些 四.简单说说你了解的类加载器 五.双亲委派机制是什么,有什么好处,怎么打破 ...

  5. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  6. 个人笔记,深入理解 JVM,很全!

    来源 | yinzige.com/2020/03/08/understanding-jvm-3ed/ 01.前言 刷豆瓣看到<深入理解 JVM>出第三版了,遂买之更新 JVM 知识,本文为 ...

  7. 专访张龙:我的漫漫程序人生路

    原文地址:http://www.csdn.net/article/2013-08-21/2816646 摘要:程序员的经历也是很多准程序员们急于想知道的,而程序员再去创业又如何呢?社区之星第32期采访 ...

  8. JVM学习笔记(自用)

    JVM学习笔记(自用) 文章目录 JVM学习笔记(自用) 1.简介 2.程序计数器 3. 虚拟机栈 4. 方法区 5. 直接内存 6. 垃圾回收 Young Collection Young Coll ...

  9. 深入理解JVM虚拟机6:深入理解JVM类加载机制

    深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...

最新文章

  1. ARM Cortex-M嵌入式C基础编程(下)
  2. 手机是怎么确定位置信息的?
  3. springmvc 登录互斥,实现避免单账户被多个地方同时登录
  4. 为什么使用GB28181而不是直接rtsp拉流
  5. Win-MASM64汇编语言-CMP/CMPSB/CMPSW/CMPSD/JNE/JCXZ
  6. 计算机组成原理 第二章 数据的表示与运算
  7. Multimodal —— 看图说话(Image Caption)任务的论文笔记(二)引入attention机制
  8. 基于Discuz的原生态MVC框架Uxf
  9. C++中容器的使用(二)
  10. java 各种数据结构,几种常见的数据结构的JAVA实现
  11. PHP响应式营销型万能H5建站系统源码
  12. 简述力法计算弹性固定无铰拱的原理_隧道结构力学计算5页
  13. 拼音分词器_自动补全
  14. 物联网网络层安全需求
  15. 基于人脸识别的门禁系统设计PPT汇报
  16. JS 实现图层模式覆盖效果
  17. Excel画的图复制到Word中变形的解决办法
  18. S3C6410(OK6410开发板介绍)
  19. 获取浏览器窗口高度和宽度兼容IE
  20. 白鹭引擎开发微信小游戏: API 调用教程文档

热门文章

  1. uni-app升级思路(前端角度)
  2. Keras安装+Pycharm配置Keras
  3. Pymediainfo读取文件夹视频长度并写入Excel文件(openpyxl)
  4. Docker学习(四):Dockerfile
  5. [Android]混淆Android代码
  6. 人工智能神经网络算法,人工智能神经网络技术
  7. Linux压缩命令gzip、tar、zip的区别和用法
  8. c语言中出现void错误,关于C语言问题
  9. 一系列国内外顶尖互联网公司的技术博客,晋升程序员必备!
  10. 鸿蒙系统乐视手机,首款骁龙870平板官宣;鸿蒙os支持第三方手机;乐视手机高调复活...