一、JVM是什么
Java虚拟机(英语:Java Virtual Machine,缩写为JVM),又名爪哇虚拟器,一种能够运行Java bytecode的虚拟机,以堆栈结构机器来进行实做。最早由太阳微系统所研发并实现第一个实现版本,是Java平台的一部份,能够运行以Java语言写作的软件程序。
 
Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。通过对中央处理器(CPU)所执行的软件实作,实现能执行编译过的Java程序码(Applet与应用程序)。
 
作为一种编程语言的虚拟机,实际上不只是专用于Java语言,只要生成的编译文件符合JVM对载入编译文件格式要求,任何语言都可以由JVM编译运行。除外,除了甲骨文,也有其他开源或闭源的实现。
——维基百科
这个描述还是很简单易懂的,虚拟机的这种机制带给了代码一种全新的生命力,就是一处编绎,到处运行。当然美好的事情总归是有些缺陷的。因为要在一台物理机器上搭建一套虚拟的体系,以此来解决各个硬件与系统间的差异问题,确实是件很美好的事情,但同时损失的自然就是运行时的效率。
 
二、JVM的体系规格
java的这套体系是种开放的规格,只要能按规格编绎出来的程序都可以跑在JVM上。JVM定义了控制Java代码解释执行和具体实现的五种规格,它们是:
  • JVM指令系统
  • JVM寄存器
  • JVM 栈结构
  • JVM 碎片回收堆
  • JVM 存储区
 
三、JVM的工作原理
 
  • 操作系统加载JVM(windows)
1.创建JVM装载环境和配置
2.装载JVM.dll
3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装载并处理class类
  • JVM加载类
下面看看一个java代码是怎么运行起来的:

 
四、JVM的内存管理
这里有一篇文章讲的很详细:http://developer.51cto.com/art/201303/387175.htm
 
JVM的内存结构分为6块:PC Register(PC寄存器)、JVM堆、JVM栈、方法区域、运行时常量、本地方法堆栈。如下图示意:
对于开发来说主要关注的还是堆和栈。
 
JVM一些参数设置:
-Xss:这个参数就是用来指定栈的大小
-Xms:设置JVM启动时最小的堆内存大小
-Xmx:设置JVM堆的最大内存大小
-XX:PermSize及-XX:MaxPermSize指定方法区域(MethodArea)的初始值与最大值
 
MethodArea对应的是持久代(PermanetGeneration),所以设置Perm的大小很重要,否则会报java.lang.OutOfMemoryError: PermGen space。
 
五、垃圾收集器(Garbage Collector,GC)
垃圾收集器这个东西对于程序员来说可谓是一种解脱,可以不用显式释放内存了。这种神奇的疗效还是要看看他的基本原理了解一下情况才行。下面摘了一段话:
有几种垃圾收集的基本策略:引用计数、标记-清除、标记-整理 (mark-compact) 和复制。此外,一些算法可以以 增量 方式完成它们的工作(不需要一次收集整个堆,使得收集暂停时间更短),一些算法可以在用户程序运行时运行( 并发收集)。其他算法则必须在用户程序暂停时一次进行整个收集(即所谓的 stop-the-world收集器)。最后,还有混合型的收集器,如 1.2 和以后版本的 JDK 使用的分代收集器,它对堆的不同区域使用不同的收集算法。
——摘自developerWorks 中国
这里就回收的算法来看主要就上面列出来的几种,其中比较重要的是“复制”和“标识-整理”有必要理解一下。
 
复制收集器就是划分两个对等空间,其中一个放活跃对象,另一个空着,等第一个满了就复制活跃对象到另一个空着的,然后将这两个空间角色换一下。这里有个重点就是只复制活跃对象。活跃对象通常就是可到达的对象也就是不用回收的内存,换言之就是除此之外的就是垃圾,那么这样的好处就是复制一次后,将那些垃圾一次回收就行了。而且复制后内存空间是会经过整理的连续的,不会有碎片问题。
 
标识-整理收集器算法结合了标记-清除和复制,代价是增加了一些收集复杂性。与标记-清除类似,标记-整理是两阶段过程,在标记阶段访问并标记每个活跃对象。然后,复制标记的对象,使所有活跃对象被整理到堆的底部。如果每一次收集时进行彻底的整理,那么得到的堆就类似于复制收集器的结果 ―― 在堆的活跃部分与自由部分有明确的界线,这样分配成本与复制收集器相当。长寿的对象趋向于沉在堆的底部,这样就不会像在复制收集器中那样反复复制它们。
 
既然是垃圾回收,那么自然有一个问题什么是垃圾?
由分配器分配的,但是用户程序不可到达的内存块。不可到达是什么意思?可以以两种方式之一访问内存块 ―― 或者用户程序在 根 (root)中有对这一内存块的引用,或者在另一个可到达的块中有对这个块的引用。
——摘自developerworks
这里面提到了一个很关键的点,就是根(Root),那什么才是Root?这个得好好了解一下。下面是GC Root的种类:
  • Class - 由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的java.lang.Class实例以其它的某种(或多种)方式成为roots,否则它们并不是roots,.
  • Thread - 活着的线程
  • Stack Local - Java方法的local变量或参数
  • JNI Local - JNI方法的local变量或参数
  • JNI Global - 全局JNI引用
  • Monitor Used - 用于同步的监控对象
  • Held by JVM - 用于JVM特殊目的由GC保留的对象,但实际上这个与JVM的实现是有关的。可能已知的一些类型是:系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。然而,JVM并没有为这些对象提供其它的信息,因此就只有留给分析分员去确定哪些是属于"JVM持有"的了。
分代垃圾收集
有人做过分析,应用程序堆中的对象有98%的对象存活的时间比较短,还有一些是会存活很长,甚至会随着应用程序整个生命周期。将这两类对象可以称为年轻代和持久代。
分代收集器(generializational collector)将堆分为多个代。在年轻的代中创建对象,满足某些提升标准的对象,如经历了特定次数垃圾收集的对象,将被提升到下一更老的代。分代收集器对不同的代可以自由使用不同的收集策略,对各代分别进行垃圾收集。
——摘自developerworks
可以看出分代垃圾收集主要是将对象以生命周期进行归类,然后针对不同的类别使用不同的回收算法,这样就可以更优的进行跟踪回收。
 
JDK 1.4.1 默认收集器

在默认情况下,JDK 1.4.1 将堆分为两部分,一个年轻的代和一个老的代(实际上,还有第三部分――永久空间,它用于存储装载的类和方法对象)。借助于复制收集器,年轻的代又分为一个创建空间(通常称为 Eden)和两个生存半空间。

老的代使用标记-整理收集器。对象在经历了几次复制后提升到老的代。小的收集将活的对象从 Eden 和一个生存半空间复制到另一个生存半空间,并可能提升一些对象到老的代。大的收集(major collection)既会收集年轻的代,也会收集老的代。 System.gc() 方法总是触发一个大的收集,这就是应该尽量少用(如果不能完全不用的话) System.gc() 的原因之一,因为大的收集要比小的收集花费长得多的时间。没有办法以编程方式触发小的收集。

——摘自developerworks

总的机制就是让寿命长的对象逐步往老的代中放,这样可以优化收集的时机,减少收集暂停给应用程序带来的影响。基本上GC的简单机制就这些内容。
 
参考文:
 
 
http://www.cnblogs.com/5207/p/4275882.html
 

Java的一些基础小知识之JVM与GC (转)的更多相关文章

  1. 学习笔记:Java的一些基础小知识之JVM与GC

      一.JVM是什么 Java虚拟机(英语:Java Virtual Machine,缩写为JVM),又名爪哇虚拟器,一种能够运行Java bytecode的虚拟机,以堆栈结构机器来进行实做.最早由太 ...

  2. Java基础小知识(一)

     序言:“不积跬步,无以至千里.不积小流,无以成江海.”每一个庞大的知识架构都是由无数个小知识点慢慢积累起来的,没有量变的积累,就没有质变上的飞跃,成功往往离不开积累. 今天就和大家分享一些我在学习J ...

  3. Java异常的一个小知识

    有以下两个代码: package com.lk.A; public class Test3 { public static void main(String[] args) { try { int a ...

  4. JAVA面向对象-----面向对象(基础预备知识汇总)

    终于整理好了面向对象基础预备知识,但是有点多,所以你们懂的,贴图,较长的代码我还是会排版出来的,我不想把时间浪费在排版上在word里排版一次已经很浪费时间了,所以请谅解. public class C ...

  5. Java基础小知识笔记

    1. Integer转进制的一个类2. toBinaryString,toOctalString,toHexString.(转为二进制,八进制,十六进制的方法)3. 如果·数据的大小没有超过byte/ ...

  6. java基础小知识

    1.1常量: 基本数据类型常量 字符常量 整数常量的表现形式:一进制的形式来表示(二进制,八进制,十进制,十六进制) 生活中:十进制(0-9)  ,星期(七进制(0-6)) ,时间(十二进制(0-11 ...

  7. java线程的一些基础小知识

    --------------------------------------------------------------------------------------------------线程 ...

  8. Java基础小知识1——分别使用字节流和字符流复制文件

    在日常使用计算机过程中经常会涉及文件的复制,今天我们就从Java代码的角度,看看在Java程序中文件复制的过程是如何实现的. 1.使用字节流缓冲区复制文件 示例代码如下: import java.io ...

  9. 刚开始学习Javascript的一些基础小知识,从入门到崩溃,希望对大家有帮助(只适合初学者)

    一.简介 1.JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型,js不能操作文件. 重要的开始啦!!!!! 引入javascript: 行间js <d ...

随机推荐

  1. 闲扯 Javascript 04 滚动条

    物体运动基础 让Div移动起来 offsetLeft的作用 用定时器让物体连续移动 效果原理 让ul一直向左移动 复制li innerHTML和+= 修改ul的width 滚动过界后,重设位置 判断过 ...

  2. android switch语句case expressions must be constant expressions

    在项目中遇到这样的Exception:case expressions must be constant expressions public class StandingCityActivity e ...

  3. 【HTML5游戏开发小技巧】RPG情景对话中,令文本逐字输出

    以前用JAVAscript实现过令文本逐字输出的效果,今天我来用html5中的canvas实现一下.canvas里的内容可不像<p>那样好操作,首先,你需要懂得一些html5的API才能操 ...

  4. H3C HCSE 官方培训胶片(中文) 下载

    H3C HCSE 官方培训胶片(中文) 点击文件名下载 HM-040 OSPF路由协议(V5.1).ppt HM-041 BGP协议原理及配置(V5.0).ppt HM-041 BGP协议原理及配置( ...

  5. JIRA初步

    JIRA 是澳大利亚 Atlassian 公司开发的一款优秀的问题跟踪管理软件工具.可以对各种类型的问题进行跟踪管理.包含缺陷.任务.需求.改进等.JIRA採用J2EE技术.可以跨平台部署.它正被广泛 ...

  6. opencv视频播放

    在一个界面上显示一张图片.是一件非常easy的事情,但说到要显示视频.刚開始学习的人可能不知道怎么处理,事实上,一般来说能够理解为视频就是图片以人眼察觉不到的速度高速更新. 曾经用摄像头採集视频显示在 ...

  7. qt下的跨目录多工程编译

    原地址:http://blog.csdn.net/fjb2080/article/details/7386292 转自:http://blog.csdn.net/high_high/article/d ...

  8. Python脚本:获取股票信息

    在水木上看到有人在问到想用python去获取股票的信息,sina finance上面的那些数据的是通过js控制的,会根据股票代码去获取实时信息然后根据用户友好的方式展示出来.首先,新浪的一个url让我 ...

  9. 基于visual Studio2013解决面试题之0604O(1)时间复杂度删除链表节点

     题目

  10. 52. 模版和设计元素——Lotus Notes的代码重用

    不论是理论上还是实用上,代码重用都是编程的一个重要议题.可以从两个角度来讨论代码重用. 一是逻辑上代码以怎样的方式被重用.既可以通过面向对象的思想普及以来耳熟能详的继承的方式.比如先建了一个车的基类, ...