首页 > 代码库 > tomcat学习笔记

tomcat学习笔记

第一章 JVM原理

一、什么是JVM

    JVM是Java Virtual Machine(Java虚拟机)的缩写。

        JAVA语言的平台无关性如何实现:通过Java虚拟机,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。

技术分享

上图为 JVM结构图

二、JAVA代码编译和执行过程

    JAVA代码编译和执行包含如下三个过程:


    1.  Java源码编译机制

    2.   类加载机制

    3.   类执行机制

     java源码编译机制

        最终将.java文件编译生成.class文件

     类加载机制

        JVM的类通过ClassLoader及其子类来完成类加载的过程,类的层次关系和加载顺序可以由下图来描述:

技术分享

        (1)Bootstrap ClassLoader

                负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

        (2)Extension ClassLoader

                负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

        (3)App ClassLoader

                负责记载classpath中指定的jar包及目录中class

        (4)Custom ClassLoader

                属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

    类执行机制

        JVM是基于栈的体系结构来执行class字节码的。线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。


三、JVM内存管理和垃圾回收

    JVM栈有堆、栈、本地方法栈、方法区组成,结构如图

技术分享

1)堆

    所有通过new创建的对象的内存都在堆中分配,堆的大小可以通过-Xmx和-Xms来控制。

        堆分为新生代老年代持久带,新生代分为EdenSurvivor(Survivor又分为fromto)

        

技术分享

    新生代:新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例

        老年代:用于存放新生代中经过多次垃圾回收仍然存活的对象

        持久带(Permanent Space):主要存放所有已加载的类信息,方法信息,常量池等等。可通过-XX:PermSize和-XX:MaxPermSize来指定持久带初始化值和最大值。Permanent Space并不等同于方法区,只不过是Hotspot JVM用Permanent Space来实现方法区而已,有些虚拟机没有Permanent Space而用其他机制来实现方法区。

技术分享

-Xmx:最大堆内存,如:-Xmx512m

-Xms:初始时堆内存,如:-Xms256m

-XX:MaxNewSize:最大年轻区内存

-XX:NewSize:初始时年轻区内存.通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%

-XX:MaxPermSize:最大持久带内存

-XX:PermSize:初始时持久带内存

-XX:+PrintGCDetails。打印 GC 信息

-XX:NewRatio 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3

-XX:SurvivorRatio 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10


2)栈

     每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果。

    -xss:设置每个线程的堆栈大小. JDK1.5+ 每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的。

3)本地方法栈

    用于支持native方法的执行,存储了每个native方法调用的状态

4)方法区

    存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(Permanet Generation)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值

-------------------------------------------------------------------------------------------------------------------------------------

JVM垃圾回收

    


本文出自 “李娜渴死” 博客,请务必保留此出处http://zhoushuyu.blog.51cto.com/7125424/1944834

tomcat学习笔记