java应用程序性能优化(Java高级编程基础:可以从这个思路去理解JVM和性能调优)java基础 / Java Web开发中的性能调优...

wufei123 发布于 2024-07-03 阅读(2)

虽然网上现在有很多对于JVM内部体系结构进行详细介绍的文章,可是我还是从我个人的理解来说一下它因为每个人对于一件东西的理解思路可能都不太一样,我不想纯粹的去复述官方文档的说明,只是想从我学习使用Java语言编程经验的角度去说一下,希望能够给各位想学习Java的小伙伴提供一个思考路径。

JVM是个什么东西?对于JVM又称Java虚拟机,其实它最初为了解决跨平台编程而设计出的一套规范的实现,这套规范从数据类型,文件存储结构,到内存和线程处理等都做了详细的约定,而实现这个约定的程序就是Java虚拟机,目前使用最多的流行Java虚拟机是

Hotspot VM,其中Oracle的JDK和OpenJDK都使用了该类型的虚拟机你可以将虚拟机理解成一个运行在操作系统上的进程,它包括了对数据类型的对接,对本地原生函数的对接,对CPU和线程的调度管理的抽象等等,这些内容几乎是在原有操作系统上面又抽象出了一个操作系统,这也就是为什么说它被称为Java虚拟机。

编程基础JVM跟我们常见的JRE,JDK等是什么关系我们一般的电脑要想能够运行Java程序就必须先安装一个称为Java运行时环境的程序,它就是JRE,只要有它,我们的Java应用程序就能够启动运行我们在JRE的基础上增加了一些开发调试的工具以及类库,就构成了我们开发人员需要安装的Java 开发工具包,JDK。

所以JVM,JRE和JDK它们三者之间的关系是JVM单指实现程序,JRE包含JVM作为底层内核,JDK有包含JRE它与我们编写的Java程序有什么关系?我们知道用Java编写的应用程序是.java类型文件,我们通过Java编译器将其编译为。

.class文件,其内容是字节码Java正是依靠这个字节码来实现了跟平台无关的开发和部署因为针对任何架构的处理器,Java的字节码都可以通过JIT来将字节码编译为对应平台的指令代码并执行如此以来就让Java应用程序的开发不必再去考虑平台问题。

JVM的内部结构说起JVM的内部结构,实际上它就是Java虚拟机程序在我们计算机内存上创建了一个大块内存空间这块空间由它负责管理由于我们要运行应用程序首先被启动的是类加载器,它的作用就是将我们应用程序用到的所有存储在各类环境里的字节码文件找出来,读取其内容,让其内容转换成一个个Class类对象实例,保存在指定的内存空间里。

其中包括JVM启动需要的基础环境类,扩展类和我们应用程序包含的自己编写的类以及引用的第三方的类,当然这个加载过程不是一次性全部加载,这些类中部分是需要预加载的,还有就是需要在运行时动态加载的理解了这些以后,我们就拿一个Java应用程序的运行过程来看,首先我们通过系统的一个句柄来开启一个主应用程序进程,该进程干的第一件事就是启动JVM的类加载模块,将相关的JVM的基础类和扩展类以及应用程序的

Classpath下的所有类都进行寻址读取内容,创建Class类实例然后,再去创建应用程序的子线程,创建子线程过程就是在应用程序管理的总空间内创建一个单向操作的栈空间,将应用程序中定义的方法和参数都封装成帧然后推入到执行的栈中。

我们将存放栈内容的空间称为栈,它随着应用程序的执行,不断的推入和移出栈帧每个帧其实就是一个方法执行的上下文,存储本地变量,临时计算结果等而我们JVM管理的最大一块公共的内存空间叫做堆,这是一块自由使用的内存空间,我们应用程序运行过程中要使用的对象实例都是在这个空间中被创建和实例化出来的。

而且这里的对象实例往往是因为某种运算需要而临时这几生成的,所以他们很少有能够持续被在整个应用程序生命周期中使用的,这就或造成应用程序管理的内存空间不足问题,所以要求JVM必须有一个专门的线程来处理这个问题,办法就是垃圾收集器,一般就是对这块空间的不再使用的类实例进行清理,对于还在使用的对象予以保留了,甚至有些内容可能会保存到整个应用程序结束。

Java入口堆空间管理有时候为了给较大的应用程序对象分配空间,可能会对享有的零散空间进行复制转移,压缩,以腾出足够的空间为未来程序执行需要其它程序这个过程被称为垃圾收集,因为收集过程中涉及到如何判别哪些对象还在被使用,哪些不再被使用,为了能够获取更大的连续空间,整理存储碎片,可能需要对空间进行复制转移,压缩等操作。

在设计垃圾收集算法时将整块空间划分为三块区域,一种是用于创建对象的区域,被称为伊甸区,在一次垃圾收集执行后,还被引用的对象会被移动到称为存活区的空间里,腾出创建区空间给接下来的新建对象使用,而对于两次垃圾收集以后还存活的引用对象,将会被移至

老年区空间存储这就是我们常说的垃圾收集算法由于我们整个应用程序在启动时对JVM管理的内存空间是有限的,我们的应用程序必须在JVM的管理调度下在这个有限的空间内创建对象,计算,销毁对象等不管努力,如果我们应用程序创建的对象需要空间太大,而我们总的堆空间太小,就会造成性能问题,严重还会造成内存溢出问题。

所以我们在编写Java应用程序时需要通过一些检查工具比如VisualVM,当然在我们安装的JDK中有很多命令行工具也能用,来不断的挑战应用程序的堆内存使用率主要是我们在运行程序时,我们可以为这些空间的分配指定大小,具体参数我们可以去查找相关说明。

通过对于代码的优化,JVM运行参数的调整,让我们的应用程序在执行过程中不会出现堆空间的浪费和不足,提高程序运行性能稳定性和效率,以及选择适当的垃圾收集策略,这个过程就是我们常说的Java应用程序调优JVM的整体视角

在我们上面说过,JVM整体分为三大块,第一块是类文件加载生成系统,第二块是应用程序数据存储和管理区域,第三块是底层代码编译和执行区域其中最重要的就是第二块,应用程序数据存储和管理区域,它严格分为堆空间和非堆空间,其中堆空间上面说过了,非堆空间就是我们常说的存放不怎么变化的内容的区域它包括方法定义区,内部的常量,静态变量等,这部分在Java 8后被称为元数据区,另外还有一部分是代码的缓冲区,方法执行的栈工作区等。

好了说完了关于JVM的整体结构,我们在进入一个重要的封装体帧看一下它的结构,帧是栈的最小执行单位,栈是后进先出型,意味着它只能从一头压入帧,然后再从压入口推出要执行的帧而这个帧我们说了它是我们要执行方法的封装体,它里面的空间被范围四大块,分别是当前方法所在类的。

常量池引用区,操作数栈,方法本地变量区,以及返回值区等。 我们的方法会被封装在它里面进行操作处理。

Java与JVMJVM如何参与Java程序执行总体来说,整个JVM参与对我们编写的Java应用程序执行的全过程,并在过程中对应用程序进行分解和结构布局首先,应用程序作为操作系统生一个进程被执行,开启其第一个主线程,调用JVM的类文件加载模块,将JVM的启动类,扩展类,以及我们应用程序编写的代码类以及我们引用的第三方类库通过加载模块调用类加载器加载并启动应用程序,其加载过程主要经历寻址读取字节码文件流,创建各种类型的Class对象,初始化静态变量,建立本地对象和Class类链接,实例化部分预加载对象。

在这个过程中,JVM会管理的内存空间会被分成三块方法区,栈区,堆区方法区是我们初始类加载过程中重要的创建区,常量,类定义,接口定义,注解元数据等内容都会存放在这里栈区是执行区,它主要是用来为线程创建执行栈空间的区域,它包括了所有线程的栈,以及本地方法栈。

最后就是堆区,是各类线程公共区,因为栈的特点是无法存放复杂的数据类型,所以我们应用程序运行过程中需要的所有引用类型,比如对象,数组,字符串等都会在这块区域创建并保存直到销毁总结一下我们的应用程序在磁盘上体现为jar包的文件系统,而被读取到内存中准备执行时,就会将字节码流转换成Class类对象存储备用,用来在需要时创建相应的实例对象。

它们在JVM里存储分布上面已经说了,理解这个布局和执行过程,就是为了更好的调度和使用这些空间,让我们的应用程序运行起来更加有效率,消耗的内存空间和资源越少,整体来说Java编程其实就是一个基于托管环境的编程,可以说是带着镣铐跳舞,我们在编写代码时主要是注意整个应用程序的需要JVM的管理内存空间大小,我们用于动态创建和存储对象空间大小,我们对于垃圾收集器算法的选择等等。

这些都可在启动程序时通过指定相关参数来调整,找到适合我们应用程序运行的最佳参数指定

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

河南中青旅行社综合资讯 奇遇综合资讯 盛世蓟州综合资讯 综合资讯 游戏百科综合资讯 新闻72362