Java:JVM内存管理(二)

Java:JVM内存管理(二)

JVM知识


在第一节中Java:JVM内存管理(一)中,我们介绍了JVM的内存结构,在介绍JVM如何管理内存之前,我们先要接触JVM的体系结构与工作方式。


六、JVM体系结构

在我们初学Java的时候一定听说过Java这么介绍自己:Java是一款面向对象的跨平台编程语言。当我们学习过Java之后,我们就会对其面向对象思想有深刻的理解,但是我们仍然不明白Java到底是如何实现一次编译到处运行的呢?


6.1 模拟计算机

JVM的全称是Java Virtual Machine(Java虚拟机),它通过模拟一台计算机来达到一台计算机所拥有的功能。那么一台真正的计算机应该具有什么样的功能呢?[1]

  • 指令集:计算机能够识别的机器语言的命令集合
  • 计算单元:能够识别并且控制指令执行的功能模块
  • 寻址方式:地址的位数、最小地址和最大地址寻址范围、以及地址的运行规则
  • 寄存器定义:包括操作数寄存器、变址寄存器、控制寄存器等定义、数量和使用方式
  • 存储单元:能够存储操作数和保存操作结构的单元、如内核缓存、内存和磁盘等

6.1.1 指令集

指令集是指能够操作CPU和控制计算机系统的一系列指令的集合,由于每一个型号的CPU作用不尽相同,所以厂商都会为自己的设备单独定义一套指令集。目前市面上主流的两套指令集从体系结构上划分位精简指令集(RISC,Reduced Instruction Set Computing)和复杂指令集(CISC,Complex Instruction Set Computing),这也就造成了像C/C++这样的直接操作硬件的语言编译出的可执行文件在其他平台上并不能正常运行的原因。

6.1.2 指令集与汇编

指令集是可以直接被计算机识别的机器码,也就是说它必须以二进制形式存放在计算机中,而汇编语言是机器码的助记符。也就是说,我们编写的每一条汇编指令,都是与机器码一一对应的。

6.1.3 指令集与CPU架构

不同的CPU架构的寄存器和段不相同,自然无法使用相同的指令集,但是现在不同的芯片厂商往往会兼容不同的指令集以吸引客户。


6.2 JVM的跨平台特性

Java的跨平台特性正是基于JVM的规范,JVM和实体机一样有一套自己的指令集,这个指令集能够被JVM解析执行。这个指令我们称之为JVM的字节码指令,凡是符合JVM规范的class字节码文件都可以被JVM执行。 
于是Java的跨平台特性就此产生,我们在任何平台上编写编译的代码都是符合JVM虚拟机规范的,而不同平台上的JVM会进行二次翻译,也就是将字节码指令翻译为JVM所在的计算机的机器码。


6.3 JVM体系结构

Java语言并不是只能运行在JVM之上,只要实现了相应的编译器Java语言就可以运行在任何平台之上(比如J++),也可以被编译为本地代码直接运行在操作系统之上,比如,Linux上的GCJ(GNU Compiler for Java)就可以把Java语言编译为本地代码直接执行。同样的,JVM上也不是只能执行Java语言,只要实现了适当的编译器,将其他语言编译为JVM上的字节码,就可以在JVM上运行。比如,JRuby,Jython以及Groovy等其他JVM语言,都会通过相应的编译器或是解释器转化为.class,然后在JVM上运行。由于JVM并不关心.class文件是由Java、JRuby、Jython等转化而来,只要这个文件结构正确并能通过class文件校验。因此,由于.class文件屏蔽了Java、JRuby等上层语言的差异,所以Java、Kotlin、Groovy等可以相互调用。[2]

JVM的运行过程

JVM的基本结构由4部分组成:

  • 类加载器,在JVM启动时或者在类运行时将需要的class文件加载进JVM
  • 执行引擎,执行引擎的任务是负责执行class文件中包含的字节码指令文件,相当于实际机器上的CPU
  • 内存区,将内存划分成若干区以模拟真实计算机的存储、记录和调度模块,如实际计算机上各种功能的寄存器或者PC指针记录器
  • 本地方法调用,调用C/C++实现本地方法的代码返回结果

七、JVM的工作机制

计算机只接受机器指令,其他高级语言必先经过编译器编译成计算机指令才能被计算机正确的执行,所以从高级语言到机器语言之间必须有个翻译的过程。

7.1 JVM引擎的架构设计

每当我们创建一个新的线程的时候,JVM会为这个线程创建一个栈,同时为这个栈分配一个PC寄存器,并且这个PC寄存器会指向这个线程中的第一行可执行代码。每当调用一个新的方法的时候会在这个栈上创建一个新的栈帧数据结构,这个栈帧会保留这个方法的一些元信息,比如方法的局部变量、一些用来支持常量池的解析、正常方法的返回以及异常处理机制等。

7.2 执行引擎的执行过程

7.2.1 Oolong介绍

Oolong是一种属于汇编的编程语言,我们之所以要介绍这门语言,是因为它能够帮助我们更好的理解class文件结构中的类信息,这些信息都是面向JVM的,也就是说只有JVM能够认识它们。所以我们先将class文件中的二进制信息转换为易读的Oolong语言,可以帮助我们理解class文件的结构。 
由于资源太难找,本人打包了一个Oolong项目,提供下载CSDN:面积分Oolong汇编查看器下载,使用时将此jar包放在与待查看的class文件同级目录下,然后双击运行即可。或者用命令行对某一指定的class文件进行反汇编Oolong.jar C:\Users\cxm\Desktop\Hello.class就可以对桌面上的Hello.class文件进行反汇编。得到一个后缀位.j的文件。

7.2.2 代码分析

首先我们通过一个具体的例子来查看执行引擎的执行过程:

 
  1. public class Test{
  2. public static void main(String[] args){
  3. int a = 2;
  4. int b = 4;
  5. int c = (a + b) * 10;
  6. }
  7. }

以下是使用Oolong得到的反汇编代码

 
  1. .source Test.java
  2. .class public super Test
  3. .super java/lang/Object
  4. .method public <init> ()V
  5. .limit stack 1
  6. .limit locals 1
  7. .line 1
  8. l0: aload_0
  9. l1: invokespecial java/lang/Object/<init> ()V
  10. l4: return
  11. .end method
  12. .method public static main ([Ljava/lang/String;)V
  13. .limit stack 2
  14. .limit locals 4
  15. .line 3
  16. l0: iconst_2
  17. l1: istore_1
  18. .line 4
  19. l2: iconst_4
  20. l3: istore_2
  21. .line 5
  22. l4: iload_1
  23. l5: iload_2
  24. l6: iadd
  25. l7: bipush 10
  26. l9: imul
  27. l10: istore_3
  28. .line 6
  29. l11: return
  30. .end method

我们只看方法,首先我们看到开篇第一个方法是来自Object的Init方法,这个方法用来对对象进行初始化,是隐式的。 
第二个方法才是我们的main方法

 
  1. .method public static main ([Ljava/lang/String;)V
  2. .limit stack 2
  3. .limit locals 4

第一行表示这个一个方法.method其访问权限是公开的public,其存储方式的静态的static,其方法名位main,其中参数[表示这是一个数组,L表示这不是一个基本数据类型,其类型是String,返回值是Void。 第二行的 stack 2 说明该方法的操作栈的最大长度为2 第三行的 locals 4 表示该方法使用了局部变量栈的最大长度为4

 
  1. .line 3
  2. l0: iconst_2
  3. l1: istore_1

.line 3表示当前运行的代码在源文件中的第三行,该行所做的操作是,将常数2入栈,将栈顶元素移至局部变量区第一位存储

 
  1. .line 4
  2. l2: iconst_4
  3. l3: istore_2

第四行的操作是将int类型的常量4入栈,然后在将其移动到局部变量区的第二位

 
  1. .line 5
  2. l4: iload_1
  3. l5: iload_2
  4. l6: iadd
  5. l7: bipush 10
  6. l9: imul
  7. l10: istore_3

第五行的操作稍显复杂,14:这里先从局部变量区中取出第一位(int 2)放到操作栈中,15:再将局部变量区中取出的第二位(int 4)压到操作栈中,16:执行加法指令(将栈中连续两次出栈的值相加再将结果压栈),17:将常量10压栈,19:执行乘法操作(将栈中连续两次出栈的值相乘并入栈)

 
  1. .line 6
  2. l11: return

第六行有一个空返回值的return语句,这也说明了当我们没有显式的添加return语句时,编译器会自动帮我们加上。

7.3 JVM方法调用栈

接下来我们分析方法调用的实现,源代码如下:

 
  1. public class Test{
  2. public static void main(String[] args){
  3. int a = 2;
  4. int b = 4;
  5. int c = add(a,b) * 10;
  6. }
  7. public static int add(int a,int b){
  8. return a+b;
  9. }
  10. }

以下是通过Oolong生成的汇编代码

 
  1. .source Test.java
  2. .class public super Test
  3. .super java/lang/Object
  4. .method public <init> ()V
  5. .limit stack 1
  6. .limit locals 1
  7. .line 1
  8. l0: aload_0
  9. l1: invokespecial java/lang/Object/<init> ()V
  10. l4: return
  11. .end method
  12. .method public static main ([Ljava/lang/String;)V
  13. .limit stack 2
  14. .limit locals 4
  15. .line 3
  16. l0: iconst_2
  17. l1: istore_1
  18. .line 4
  19. l2: iconst_4
  20. l3: istore_2
  21. .line 5
  22. l4: iload_1
  23. l5: iload_2
  24. l6: invokestatic Test/add (II)I
  25. l9: bipush 10
  26. l11: imul
  27. l12: istore_3
  28. .line 6
  29. l13: return
  30. .end method
  31. .method public static add (II)I
  32. .limit stack 2
  33. .limit locals 2
  34. .line 9
  35. l0: iload_0
  36. l1: iload_1
  37. l2: iadd
  38. l3: ireturn
  39. .end method

这里我们可以看到这样一段代码

 
  1. l6: invokestatic Test/add (II)I

这是一段跳转指令,调用一个Test类中方法签名为add (II)I的方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理,美食推荐管理,酒店推荐管理,周边推荐管理,分享圈管理,我的收藏管理,系统管理。用户可以在微信小程序上注册登录,进行每日签到,防疫查询,可以在分享圈里面进行分享自己想要分享的内容,查看和收藏景点以及美食的推荐等操作。因而具有一定的实用性。 本站后台采用Java的SSM框架进行后台管理开发,可以在浏览器上登录进行后台数据方面的管理,MySQL作为本地数据库,微信小程序用到了微信开发者工具,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得旅游社交小程序管理工作系统化、规范化。 管理员可以管理用户信息,可以对用户信息添加修改删除。管理员可以对景点推荐信息进行添加修改删除操作。管理员可以对分享圈信息进行添加,修改,删除操作。管理员可以对美食推荐信息进行添加,修改,删除操作。管理员可以对酒店推荐信息进行添加,修改,删除操作。管理员可以对周边推荐信息进行添加,修改,删除操作。 小程序用户是需要注册才可以进行登录的,登录后在首页可以查看相关信息,并且下面导航可以点击到其他功能模块。在小程序里点击我的,会出现关于我的界面,在这里可以修改个人信息,以及可以点击其他功能模块。用户想要把一些信息分享到分享圈的时候,可以点击新增,然后输入自己想要分享的信息就可以进行分享圈的操作。用户可以在景点推荐里面进行收藏和评论等操作。用户可以在美食推荐模块搜索和查看美食推荐的相关信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值