微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JVM基础篇

最开始附上标准官方文档链接地址:https://docs.oracle.com/javase/8/docs/index.html

一.总览
1.1java的全部组件图(java8标准文档的原图——很经典)

在这里插入图片描述

组件:就是由窗口或者类等组成的专门用于完成某类功能的集合。

1.2.上图中每一个组件的作用

       java: 该java命令启动 Java 应用程序。它通过启动 Java 运行时环境 (JRE)、加载指定的类并调用该类的main() 方法来完成此操作。
       
       javac:  Java编程语言编译器,javac读取用Java编程语言编写的源文件,并将它们编译成字节码类文件。

       javadoc:  是sun公司提供的一个技术,它从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的api帮助文档。
       也就是说,只要在编写程序时以一套特定的标签作注释,在程序编写完成后,通过javadoc就可以同时形式程序的开发文档了。

       jar:  可以将程序打包,打包后可以一次性下载,由于jar还有压缩功能,这就更加快了下载的速度。

       javap: 反汇编一个或多个类文件。

       jdeps:  Java 类依赖分析器,执行命令后用来显示类之间的依赖关系

       Scripting --- Troubleshooting 组件都是工具,详细作用这里附上链接
       https://docs.oracle.com/javase/8/docs/technotes/tools/index.html#scripting    
      

1.3 jre里有什么?

       用户页面工具包:
       
       java web start:   Java Web Start 是一种应用程序部署技术,使您能够从 Web 浏览器单击一下即可启动功能齐全的应用程序。

        Applet / Java Plug-in:  本主题提供有关开发和部署 Java 小程序的信息。Java 小程序使用Java Plug-in 技术在浏览器中运行。

        JavaFX:  是一组图形和媒体包,使开发人员能够设计、创建、测试、调试和部署在不同平台上一致运行的客户端应用程序。

        Swing:  Swing 实现了一组组件,用于构建图形用户界面 (GUI) 并向 Java 应用程序添加丰富的图形功能和交互性。Swing 组件完全用 Java 编程语言实现。可插拔的外观让您可以创建跨平台外观相同的 GUI。
         
        Java 2D:  Java 2D API 是一组用于高级 2D 图形和成像的类。它在一个综合模型中包含艺术线条、文本和图像。API 为图像合成和 Alpha 通道图像提供了广泛的支持,提供了一组提供准确色彩空间定义和转换的类,
        以及一组丰富的面向显示的成像操作符。这些类是作为java.awt和java.awt.image包的补充提供的 。
        
        AWT:  Swing类建立在AWT架构之上,支持图形用户界面 (GUI) 编程。
        
        Java Accessibility Guide:  Java 可访问性指南。
        
        Drag and Drop:   拖放支持跨 Java 编程语言和本机应用程序、Java 编程语言应用程序之间以及单个 Java 编程语言应用程序内的数据传输。
        
        Java Input Method Framework (IMF) Technology:Java 输入法框架 (IMF) 技术
        
        Java Image I/O Technology:  通过JSR-015开发的 Java Image I/O API提供了一种可插拔架构,用于处理存储在文件中并通过网络访问的图像。与以前用于加载和保存图像的 API 相比,它提供了更多的灵活性和功能。
        
        Java Print Service:  Java Print Service API 包括一个可扩展的打印属性集,该属性集基于 IETF 的 Internet 打印协议 (IPP) 1.1 中指定的标准属性。通过属性,客户端和服务器应用程序可以发现和选择具有属性指定功能的打印机。

        Java Sound Technology:  Java 平台包括一个强大的 API,用于捕获、处理和回放音频和 MIDI(乐器数字接口)数据。此 API 由高效的声音引擎支持,可保证平台的高质量音频混合和 MIDI 合成功能。
        
        集成库:
        
        IDL:  Java IDL 技术向 Java 平台添加了 CORBA(通用对象请求代理架构)功能,提供基于标准的互操作性和连接性。Java IDL 使分布式启用 Web 的 Java 应用程序能够使用由对象管理组定义的行业标准 IDL
        (对象管理组接口定义语言)和 IIOP(Internet Inter-ORB 协议)透明地调用对远程网络服务的操作。运行时组件包括一个 Java ORB,用于使用 IIOP 通信进行分布式计算。
        
        JDBC:  ava 数据库连接 (JDBC) API 提供来自 Java 编程语言的通用数据访问。使用 JDBC API,您几乎可以访问任何数据源。
        
        Java Naming and Directory Interface (JNDI):  Java 命名和目录接口 (JNDI) 为用 Java 编程语言编写的应用程序提供命名和目录功能。
        
        The Java Remote Method Invocation API (Java RMI):Java 远程方法调用 (Java RMI) 使程序员能够创建基于 Java 技术的分布式应用程序到基于 Java 技术
        的应用程序,其中远程 Java 对象的方法可以从其他 Java 虚拟机(可能在不同的主机上)调用。
          
        Java RMI over IIOP(RMI-IIOP):RMI-IIOP 利用 Java CORBA 对象请求代理 (ORB) 和 IIOP,因此您可以用 Java 编程语言编写所有代码,并使用rmic编译器生成通过 Internet InterORB 协议连接应用程序所需的代码
        ( IIOP) 给以任何 CORBA 兼容语言编写的其他语言。要使用其他语言的 CORBA 应用程序,可以使用带有-idl选项的rmic编译器从 Java 编程语言接口生成 IDL 。要生成 IIOP 存根和绑定类,请使用带有-iiop选项的rmic编译器。
        
        Scripting for the Java Platform(Scripting):许多脚本和动态类型语言的实现都会生成 Java 字节码,以便程序可以在 Java 平台上运行,就像实际的 Java 程序一样。
        以这种方式实现一种语言(或作为脚本语言的 Java 解释器类)提供了 Java 平台的所有优点:脚本实现可以利用 Java 平台的二进制可移植性、安全性和高性能字节码执行。
        Other Base Libraries --其他类库:
        lang and util Base Libraries -- 基础类库:

二、JVM调优

2.1JVM调优重点在那几个部分?
Heap、JIT Complier、Garbage Collector三个部分,因为它们内存放对象的生命周期较长,会持续占用内存空间,所以可以根据实际业务场景对其进行合适的空间分配,可以提高程序运行的性能

运行时数据区简介:
运行时数据区包括五个部分 Method Area、Heap、Java Threads、Program Counter Registers、Native Internal Threads这五个部分组成的,这里有些跟随虚拟机启动而创建,随着虚拟机关闭而销毁,剩下的那些跟线程的生命周期绑定在一起。

方法一个java进程只有一个方法区,被所有java线程共享,所以线程不安全,内部存储类的结构、运行时常量池、字段、方法、构造函数等。
要注意:不同JDK版本里使用的这一部分有不同的名称,JDK<=1.7称之为永久代,而JDK>=1.8则称之为元空间
这里介绍了方法区是包含运行时常量池的,那么常量池和它有关系么?
有关系,常量池存在于class文件中,是在硬盘上的,而将它加载到内存中就变成了运行时常量池,这就很直观了。

:主要存储类的实例信息和数组,和方法区相同,被所有java进程共享,所以线程非安全,那各种数据类型存放在哪里呢?基本数据类型保存在栈内存中,因为基本数据类型占用空间小、大小固定,通过按值来访问,属于被频繁使用的数据。例如n=3,我认为能存放3这个常量的n这个变量的空间一定是一个可以线程共享的空间,所以在栈上。如果是对象,栈上则保存变量名加地址引用,实际值存放在堆上,实际如下图

在这里插入图片描述

这个图原图来自https://blog.csdn.net/weixin_27808545/article/details/112140801
如果禁止转载请联系我删除
下面例子的两个图也来自上面这篇博客

let a = 20;
let b = a;
b = 30;
console.log(a); // 此时a的值是多少,是30?还是20?


答案是:20

发生了如图过程:

在这里插入图片描述

let m = { a: 10, b: 20 };
let n = m;
n.a = 15;
console.log(m.a) //此时m.a的值是多少,是10?还是15?

答案是:15

发生了如图过程:

在这里插入图片描述

静态变量存放在哪里呢?应该是存放在方法区里,方法区不仅仅存放静态变量还存放方法,但是只存放java里的方法,native方法存在本地方法栈里,如果在java方法调用了本地方法,那么会在栈里通过动态链接 Native Method Interface调用在本地方法栈中压栈的本地方法,下面我们就用一段代码来理解一下方法栈区

这个示例及原图来自https://blog.csdn.net/wqq3670/article/details/105401190?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%96%B9%E6%B3%95%E5%9C%A8jvm%E7%9A%84%E5%93%AA%E9%87%8C&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-5-105401190.pc_search_es_clickV2&spm=1018.2226.3001.4187
如果禁止转载请联系我删除

public class TestDemo {
    public static void main(String[] args) {
        test();
    }

    private static void test() {
        for (int i = 0; i < 10; i++) {
            int ret = myadd(i,i+1);
            System.out.print(ret+" ");
        }
    }

    private static int myadd(int i, int j) {
        return i + j;
    }
}

在这里插入图片描述


3.The PC Register:每个java虚拟机线程都有一个私有的PC Register,负责指向当前线程方法执行的位置。

在这里插入图片描述


三、字节码文件怎么来?如何解读?

字节码文件:有固定格式的16进制文件,具体如下图:

在这里插入图片描述


原User.java如下图

在这里插入图片描述

第二部分的图是JVM的大概架构,可以看到JVM最开始收到的就是一个Class文件,那么这个Class文件哪里来的呢?
首先 javac User.java -->User.class
这个Class文件里包含什么东西?
每个Class文件包含了类和接口的总体情况,并且以16进制的情况进行展示。
这个文件的架构什么样?
架构说明:https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html

在这里插入图片描述


通常这个Class文件是以magic开头,u2代表4位,u4代表8位,转化成16进制就是cafe babe,若果将开头的cafe babe 修改了使用java命令运行就会出错。

在这里插入图片描述


从.Class文件的第一列可以看出 cafe babe 后的0000是miner version,0034是major version,0034的16进制转化为10进制的结果是52,而这个52根据下表代表着JDK8这个版本号。
对照表链接:https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html

在这里插入图片描述


再往下就是constant_pool_count这个代表的是常量的个数,0043转化成10进制就是67,在看看上边的User.java好像所有的变量加起来也远远达不到这个数量…难道是Class文件出错了么?实际上并不是,我们再往下看,

在这里插入图片描述


这里说constant_pool_count这个值等于constant_pool + 1 = 67,constant_pool = constant_pool_count - 1 = 66?好像还是有点多…
再看一下文档:

在这里插入图片描述


文档说constant_pool这个常量数组里的常量是下边这个结构

在这里插入图片描述


这里u1代表1位,tag代表这个常量的类型,后边取两位0a是10代表的是一个方法级的常量,对照表如下:

在这里插入图片描述


那么后边的info[]如何解析呢?其实这里继续看文档的下边

在这里插入图片描述


因为这是一个方法级的常量所以我们找这个方法级的info[],通过观察它的结构,发现它的class index占4位是0010 = 16,name_and_type_index也占4位是0011 = 35,照这个方式可以一直翻译到第66个常量,这里就不一一解释了,常量的翻译结果是这样

在这里插入图片描述


最后我们可以使用javap -v -c -p XXX.java 命令验证一下生成下面结果

在这里插入图片描述


在这里插入图片描述


跟我们解析的结果基本吻合,所以按道理来讲如果你能写出像上边的这个class文件那么就可以交给jvm去执行,来达到最终的效果,所以无论这个class文件是由java源程序编译而来的还是c语言或者PHP编译而来的都可以。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐