Java虚拟机JVM性能优化(一):JVM知识总结(2)
这就是表面上每一个应用执行的场景,但是现在我们来探究下当你执行java命令时究竟发生了什么。Java虚拟机是什么?大多数开发人员通过持续调试来与JVM交互——aka selecting 和value-assigning启动选项能让你的Java程序跑的更快,同时避免了臭名昭著的”out of memory”错误。但是,你是否曾经想过,为什么我们起初需要一个JVM来运行Java应用呢?
什么是Java虚拟机?
简单的说,一个JVM是一个软件模块,用于执行Java应用字节码并且把字节码转化到硬件,操作系统特殊指令。通过这样做,JVM允许Java程序在第一次编写后可以在不同的环境中执行,并不需要更改原始的代码。Java的可移植性是通往企业应用语言的关键:开发者并不需要为不同平台重写应用代码,因为JVM负责翻译和平台优化。
一个JVM基本上是一个虚拟的执行环境,作为一个字节码指令机器,而用于分配执行任务和执行内存操作通过与底层的交互。
一个JVM同样为运行的Java应用照看动态资源管理。这就意味着它掌握分配和释放内存,在每个平台上保持一致的线程模型,在应用执行的地方用一种适于CPU架构的方式组织可执行的指令。JVM把开发人员从跟踪对象当中的引用,和它们需要在系统中存在多长时间中解放出来。同样的它不用我们管理何时去释放内存——一个像C语言那样的非动态语言的痛点。
你可以把JVM当做是一个专门为Java运行的操作系统;它的工作是为Java应用管理运行环境。一个JVM基本上是一个虚拟的通过与底层的交互的执行环境,作为一个字节码指令机器,而用于分配执行任务和执行内存操作。
JVM组件概述
有很多写JVM内部和性能优化的文章。作为这个系列的基础,我将会总结概述下JVM组件。这个简短的阅览会为刚接触JVM的开发者有特殊的帮助,会让你更想了解之后更深入的讨论。
从一种语言到另一种——关于Java编译器
编译器是把一种语言输入,然后输出另一种可执行的语句。Java编译器有两个主要任务:
1. 让Java语言更加轻便,不用在第一次写的时候固定在特定的平台;
2. 确保对特定的平台产生有效的可执行的代码。
编译器可以是静态也可以是动态。一个静态编译的例子是javac。它把Java代码当做输入,并转化为字节码(一种在Java虚拟机执行的语言)。静态编译器一次解释输入的代码,输出可执行的形式,这个是在程序执行时将被用到。因为输入是静态的,你将总能看到结果相同。只有当你修改原始代码并重新编译时,你才能看到不同的输出。
动态编译器,例如Just-In-Time (JIT)编译器,把一种语言动态的转化为另一种,这意味着它们做这些时把代码被执行。JIT编译器让你收集或创建运行数据分析(通过插入性能计数的方式),用编译器决定,用手边的环境数据。动态的编译器可以在编译成语言的过程之中,实现更好的指令序列,把一系列的指令替换成更有效的,甚至消除多余的操作。随着时间的增长你将收集更多的代码配制数据,做更多更好的编译决定;整个过程就是我们通常称为的代码优化和重编译。
动态编译给了你可以根据行为去调整动态的变化的优势,或随着应用装载次数的增加催生的新的优化。这就是为什么动态编译器非常适合Java运行。值得注意的是,动态编译器请求外部数据结构,线程资源,CPU周期分析和优化。越深层次的优化,你将需要越多的资源。然而在大多数环境中,顶层对执行性能的提升帮助非常小——比你纯粹的解释要快5到10倍的性能。
分配会导致垃圾回收
分配在每一个线程基于每个“Java进程分配内存地址空间”,或者叫Java堆,或者直接叫堆。在Java世界中单线程分配在客户端应用程序中很常见。然而,单线程分配在企业应用和工作装载服务端变的没有任何益处,因为它并没有使用现在多核环境的并行优势。
并行应用设计同样迫使JVM保证在同一时间,多线程不会分配同一个地址空间。你可以通过在整个分配空间中放把锁来控制。但这种技术(通常叫做堆锁)很消耗性能,持有或排队线程会影响资源利用和应用优化的性能。多核系统好的一面是,它们创造了一个需求,为各种各样的新的方法在资源分配的同时去阻止单线程的瓶颈,和序列化。
一个常用的方法是把堆分成几部分,在对应用来说每个合式分区大小的地方——显然它们需要调优,分配率和对象大小对不同应用来说有显著的变化,同样线程的数量也不同。线程本地分配缓存(Thread Local Allocation Buffer,简写:TLAB),或者有时,线程本地空间(Thread Local Area,简写:TLA),是一个专门的分区,在其中线程不用声明一个全堆锁就可以自由分配。当区域满的时候,堆就满了,表示堆上的空闲空间不够用来放对象的,需要分配空间。当堆满的时候,垃圾回收就会开始。
碎片
- 上一篇:Java虚拟机JVM性能优化(二):编译器
- 下一篇:Java锁之自旋锁详解