zoukankan      html  css  js  c++  java
  • JVM内存管理

    前几天公司的郑大晔校上,XXX同事做了JVM的Session,于是趁端午节放假的功夫,研究了一些JVM相关的知识。

    在Java生态系统中,JVM占据至关重要的作用,就像一个适配器,它向编程语言(主要是Java)屏蔽了操作系统的差异,所以实现了“一次编写,到处运行”的理想;同时也向操作系统屏蔽了编程语言之间的差异,能让Java、Clojure、JRuby、JPython、Groovy等高级语言运行于Java虚拟机之上;可以说,JVM完全实现了跨系统跨语言的支持。

    如果以Jeffery Richter的眼光看来,JVM在某种程度上,也应该算作是它自己的操作系统,因为它有自己的内存管理器、自己的安全系统、自己的文件加载器,自己的错误处理机制、自己的线程处理模型;总之一句话,JVM是相当的牛B。

    (跑题一下,正所谓“理想很丰满、现实很骨干”,iOS上根本无法运行JVM,原因很简单,苹果公司禁止在iOS中使用及时编译;这也是为什么Mono在开发完成后也只得将源代码直接编译为Native Code;可能很多人会说,我们不能用边解释边执行的方式在iOS上运行Java程序么?至于这个问题,下面再谈......归根结底,“一次编写,到处运行”有时候并不是你想像的那样牛X)。

    言归正传,自Java诞生以来,历史上曾产生过很多优秀的虚拟机,最出名的要数Sun公司的Classic VM和HotSpot VM,前者在JDK1.1和1.2时使用得比较多,它是用纯解释器的方式来执行Java代码,一发布后便引起了极大的轰动,当然也为Java博得了“Java语言很慢”的“美誉”;但随着虚拟机技术的不断发展和理论的不断完善,在JDK1.2之后Sun公司发布了新一代的虚拟机-----HotSpot VM,开发人员在这款虚拟机中内置了JIT编译器并使之具有了热点代码探测能力,及如果一段Java方法被调用次数达到了一定程度之后,就会被视为热点代码并交给JIT编译器及时编译成本地代码,以提高运行速度。

    JVM的一个重要的特征就是它的自动内存管理机制,在执行一段Java代码的时候,会把它所管理的内存划分成几个不同的数据区域,其中包括:

    1. 程序计数器,众所周知,JVM的多线程是通过线程轮流切换并分配CPU执行时间的方式来实现的,那么每一个线程在切换后都必须记住它所执行的字节码的行号,以便线程在得到CPU时间时进行恢复,这个计数器用于记录正在执行的字节码指令的地址,这里要强调的是“字节码”,如果执行的是Native方法,那么这个计数器应该为null;
    2. Java计算栈,可以说整个Java程序的执行就是一个出栈入栈的过程,JVM会为每一个线程创建一个计算栈,用于记录线程中方法的调用和变量的创建,由于在计算栈里分配的内存出栈后立即被抛弃,因此在计算栈里不存在垃圾回收,如果线程请求的栈深度大于JVM允许的深度,会抛出StackOverflowError异常,在内存耗尽时会抛出OutOfMemoryError异常;
    3. Native方法栈,JVM在调用操作系统本地方法的时候会使用到这个栈;
    4. Java堆,由于每个线程分配到的计算栈容量有限,对于可能会占据大量内存的对象,则会被分配到Java堆中,在栈中包含了指向该对象内存的地址;对于一个Java程序来说,只有一个Java堆,也就是说,所有线程共享一个堆中的对象;由于Java堆不受线程的控制,如果在一个方法结束之后立即回收这个方法使用到的对象,并不能保证其他线程是否正在使用该对象;因此堆中对象的回收由JVM的垃圾收集器统一管理,和某一个线程无关;在HotSpot虚拟机中Java堆被划分为三代:
      • 新生代,正常情况下新创建的对象会被分配到新生代,但如果对象占据的内存足够大以致超过了新生代的容量限制,也可能被分配到老年代;新生代对象的一个特点是最新、且生命周期不长,被回收的可能性高;
      • 老年代,除了上述所说的大对象会被直接分配在老年代之外,一个在新生代的对象历经多次垃圾回收之后,也会被直接拷贝至老年代,当然老年代的容量要比新生代大得多;
      • 永久代,永久代并不存储对象,而是存储一些JVM加载的类信息、常量、静态变量、JIT编译后生成的代码等,JVM也会在内存空间不足的情况下对永久代进行回收;
    5. 直接内存,自JDK1.4新加入NIO类之后,Java程序便可以使用Native函数库直接分配堆外内存,然后通过一个存储在堆中的DirectByteBuffer对象来对这块内存的引用进行操作;直接内存的容量不受堆容量的限制。
  • 相关阅读:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    php使用 _before_index() 来实现访问页面前,判断登录
    php使用 _before_index() 来实现访问页面前,判断登录
    查询方式实例演示
    查询方式实例演示
    haproxy timeout server 46000 后台超时时间
    haproxy timeout server 46000 后台超时时间
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
  • 原文地址:https://www.cnblogs.com/cdutedu/p/3763563.html
Copyright © 2011-2022 走看看