- 浏览: 897766 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
天天来注册:
...
try catch finally 用法 -
tadpole_java:
谢谢你的分享。
二十七、Qt数据库(七)QSqlRelationalTableModel(转) -
359449749tan:
android之EditText文本监听(addTextChangedListener) -
michael_wang:
人过留名 多谢分享
Android NOtification 使用 -
wilsonchen:
wangqi0614 写道这个删除是删除所有的把?能不能值删除 ...
Android的SharedPreferences保存与删除数据简单实例
引用
第一部分:JVM基本结构
1.什么是JVM
一个java的application对应了一个java.exe/javaw.exe(java.exe和javaw.exe你可以把它看成java的虚拟机,一个有窗口界面一个没有)。你运行几个application就有几个java.exe/javaw.exe。或者更加具体的说,你运行了几个main函数就启动了几个java应用,同时也启动了几个java的虚拟机。通过java.exe或者javaw.exe来启动一个虚拟机实例。
2.JVM的生命周期
java的虚拟机中有两种线程,一种叫叫守护线程,一种叫非守护线程,main函数就是个非守护线程,虚拟机的gc就是一个守护线程。java的虚拟机中,只要有任何非守护线程还没有结束,java虚拟机的实例都不会退出,所以即使main函数这个非守护线程退出,但是由于在main函数中启动的匿名线程也是非守护线程,它还没有结束,所以jvm没办法退出。
package com.jvm.sym; public class TestJVM { /** * @param args */ public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { try { Thread.currentThread().sleep(i * 10000); System.out.println("睡了" + i * 10 + "秒"); } catch (InterruptedException e) { System.out.println("干嘛吵醒我"); } } } }).start(); for (int i = 0; i < 50; i++) { System.out.print(i); } } } /*打印结果:0睡了0秒 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849睡了10秒 睡了20秒 睡了30秒 睡了40秒 */
引用
3.JVM的体系结构
如下图所示:图一
4.JVM体系各个模块之间的调用情况:
图二
当一个classLoder启动的时候,classLoader的生存地点在jvm中的堆,然后它会去主机硬盘上将A.class装载到jvm的方法区,方法区中的这个字节文件会被虚拟机拿来new A字节码(),然后在堆内存生成了一个A字节码的对象,然后A字节码这个内存文件有两个引用一个指向A的class对象,一个指向加载自己的classLoader
5.方法区的功能
如图三
//举例方法区功能 package test;import java.io.Serializable;public final class ClassStruct extends Object implements Serializable {//1.类信息 //2.对象字段信息 private String name; private int id; //4.常量池 public final int CONST_INT=0; public final String CONST_STR="CONST_STR"; //5.类变量区 public static String static_str="static_str"; //3.方法信息 public static final String getStatic_str ()throws Exception{ return ClassStruct.static_str; }}
引用
其实内存的字节码块就是完整的把整个类装到了内存而已
a.类信息:修饰符(public final)
是类还是接口(class,interface)
类的全限定名(Test/ClassStruct.class)
直接父类的全限定名(java/lang/Object.class)
直接父接口的权限定名数组(java/io/Serializable)
也就是 public final class ClassStruct extends Object implements Serializable这段描述的信息提取
b.字段信息:修饰符(pirvate)
字段类型(java/lang/String.class)
字段名(name)
也就是类似private String name;这段描述信息的提取
c.方法信息:修饰符(public static final)
方法返回值(java/lang/String.class)
方法名(getStatic_str)
参数需要用到的局部变量的大小还有操作数栈大小(操作数栈我们后面会讲)
方法体的字节码(就是花括号里的内容)
异常表(throws Exception)
也就是对方法public static final String getStatic_str ()throws Exception的字节码的提取
d.常量池:
d.1.直接常量:
1.1CONSTANT_INGETER_INFO整型直接常量池public final int CONST_INT=0;
1.2CONSTANT_String_info字符串直接常量池 public final String CONST_STR="CONST_STR";
1.3CONSTANT_DOUBLE_INFO浮点型直接常量池
等等各种基本数据类型基础常量池(待会我们会反编译一个类,来查看它的常量池等。)
d.2.方法名、方法描述符、类名、字段名,字段描述符的符号引用
也就是所以编译器能够被确定,能够被快速查找的内容都存放在这里,它像数组一样通过索引访问,就是专门用来做查找的。
编译时就能确定数值的常量类型都会复制它的所有常量到自己的常量池中,或者嵌入到它的字节码流中。作为常量池或者字节码流的一部分,编译时常量保存在方法区中,就和一般的类变量一样。但是当一般的类变量作为他们的类型的一部分数据而保存的时候,编译时常量作为使用它们的类型的一部分而保存
e.类变量:
就是静态字段( public static String static_str="static_str";)
虚拟机在使用某个类之前,必须在方法区为这些类变量分配空间。
f.一个到classLoader的引用,通过this.getClass().getClassLoader()来取得为什么要先经过class呢?思考一下,然后看第七点的解释,再回来思考
g.一个到class对象的引用,这个对象存储了所有这个字节码内存块的相关信息。所以你能够看到的区域,比如:类信息,你可以通过this.getClass().getName()取得
所有的方法信息,可以通过this.getClass().getDeclaredMethods(),字段信息可以通过this.getClass().getDeclaredFields(),等等,所以在字节码中你想得到的,调用的,通过class这个引用基本都能够帮你完成。因为他就是字节码在内存块在堆中的一个对象
h.方法表,如果学习c++的人应该都知道c++的对象内存模型有一个叫虚表的东西,java本来的名字就叫c++- -,它的方法表其实说白了就是c++的虚表,它的内容就是这个类的所有实例可能被调用的所有实例方法的直接引用。也是为了动态绑定的快速定位而做的一个类似缓存的查找表,它以数组的形式存在于内存中。不过这个表不是必须存在的,取决于虚拟机的设计者,以及运行虚拟机的机器是否有足够的内存
4.总结:
首先,当一个程序启动之前,它的class会被类装载器装入方法区(不好听,其实这个区可叫做Permanent区),执行引擎读取方法区的字节码自适应解析,边解析就边运行(其中一种方式),然后pc寄存器指向了main函数所在位置,虚拟机开始为main函数在java栈中预留一个栈帧(每个方法都对应一个栈帧),然后开始跑main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行的时候,操纵系统会为本地方法分配本地方法栈,用来储存一些临时变量,然后运行本地方法,调用操作系统API等。
第二部分:JVM的各个模块的功能
在这个之前首先考虑下Java的内存管理系统,由于Java的内存管理系统实际包含两方面的内容:内存的分配和垃圾的回收。由于Java采用的自动的内存管理方式,程序员不用考虑内存管理的细节,那为什么需要去了解呢?原因有三个:
a.由于在新的线程创建时,JVM会为每个线程创建一个专属的栈(stack),这样就要求不能用过多的递归,容易导致stack overflow。
b.一旦内存出现问题,容易找到根源。
c.有优化JVM,使得优化应用。
下面就分别将各个模块:
1.类装载子系统:负责把类从硬盘上中装入内存的方法区;
2.垃圾收集器:主要是收回不再允许的程序引用对象所占用的内存,它可能负责还在使用的对象,以减少堆对象。
3.执行引擎:有四种方式:
a、最简单的:一次性解释字节码。
b、快,但消耗内存的:“即时编译器”,第一次被执行的字节码会被编译成机器代码,放入缓存,以后调用可以重用。
c、自适应优化器,虚拟机开始的时候会解释字节码,但是会监视运行中程序的活动,并记录下使用最频繁的代码段。程序运行的时候,虚拟机只把使用最频繁的代码编译成本地代码,其他的代码由于使用的并不频繁,继续保留为字节码--由虚拟机继续解释他们。一般可以使java虚拟机80%~90%的时间里执行被优化过的本地代码,只需要编译10%~20%对性能优影响的代码。
d、由硬件芯片组成,他用本地方法执行java字节码,这种执行引擎实际上是内嵌在芯片里的。
4.pc寄存器:JVM的PC寄存器的功能是存放将要执行指令的地址。每个JVM支持多个线程同时进行,每个JVM都有自己的PC寄存器。在任何一个点,每个JVM线程执行单个方法的代码,这个方法是线程的当前方法。如果方法不是native的,程序计数器寄存器包含了当前执行的JVM指令的地址,如果方法是 native的,程序计数器寄存器的值不会被定义。
5.栈
JVM是基于栈的虚拟机.JVM为每个新创建的线程都分配一个栈.也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。
6.堆:
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
6.1栈和堆的比较:
栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方 。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
栈的优势是,存取速度比堆要快 ,仅次于直接位于CPU中的寄存器。
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。
7.方法区:
VM有一个被所有的线程共享方法区。方法区类似于传统语言的编译后代码的存储区,或者UNIX进程中的text段。它存储每个类结构例如常量池(constant pool),成员字段域和方法和构造函数,包含类和实例初始化和接口类型类型中用到的特殊方法的代码。
方法区在虚拟机启动时创建。尽管方法区在逻辑上时heap的一部分,简单的实现仍然可以选择对它既不回收也不压缩。
引用
JVM监控
1.jstatd
启动jvm监控服务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
2.jps
列出所有的jvm实例
3.jconsole
一个图形化界面,可以观察到java进程的gc,class,内存等信息。虽然比较直观,但是个人还是比较倾向于使用jstat命令
4.jinfo(linux下特有)
观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数
5.jmap(linux下特有,也是很常用的一个命令)
观察运行中的jvm物理内存的占用情况。
6.jstat
这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
发表评论
-
判断两二叉树相等
2014-05-29 00:13 1093bool IsBSTEqual(BNode* root1, ... -
数据去重
2014-05-29 00:11 767引用 使用数据结构丰富的脚本语言,如Python,利用其中的字 ... -
判断一个整数是否为2的次方幂
2014-05-28 23:56 842/* 判断一个整数是否为2的次方幂 */ bool ... -
实现Comparable接口,进行排序
2014-05-28 23:47 8794import java.util.ArrayList; ... -
Struct2详解
2014-05-21 15:14 882引用 Servlet的缺点: 1、web.xml配置比较多 2 ... -
常用方法
2014-04-25 20:24 741[color=red]String[/color] ... -
java nio和io的比较
2014-04-16 19:49 1695引用 第一部分:简单介绍NIO 服务器在合理时间内处理 ... -
Struts2、Spring3、HIbernate4总结
2014-04-16 10:35 831引用 第一部分:Struts2 1 ... -
Finally的使用总结
2014-04-15 22:02 843//清单一: public class ... -
Fibonacci数列的递归与非递归
2014-04-15 20:57 685//非递归实现 //f(1)=1,f(2)=1,f(n) ... -
Java中的异常
2014-04-14 09:42 597引用 Throwable包括两个子类:Error和Except ... -
JVM的垃圾回收机制
2014-04-13 18:39 825引用 堆被划分为新生代和旧生代, 新生代包含Eden 和 S ... -
集合类总结
2014-04-04 15:54 624引用 一. 总的框架 总的有Collection和Map Co ... -
设计模式之策略模式
2014-04-01 17:07 596main ======================= ... -
设计模式之责任链模式
2014-04-01 16:32 710main ======================= ... -
设计模式之访问者模式
2014-03-31 18:57 828main ======================= ... -
设计模式之工厂模式
2014-03-31 11:33 612main ======================= ... -
设计模式之观察者模式
2014-03-30 15:04 827main =============== ... -
Java中的反射机制Reflect
2014-03-28 17:17 3569package com.reflect.sym; i ... -
IOC原理详解
2014-03-28 09:54 1008引用 1.当不用IOC时: 在采用面向对象方法设计的软件系统中 ...
相关推荐
详细介绍了java虚拟机和java内存区域的描述解释,并针对堆和栈的内存溢出进行了案例描述,是不可多得的分享资料
一个文档让你读懂什么事java虚拟机,让你的编程生涯更加的透彻!
JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)
jvm详解高清pdf版,本文详细讲解了 JVM(Java Virtual Machine)的方方面面,首先由 java 的特性来描绘 JVM 的大致应用,再细细阐述了 JVM 的原理及内存管理机制和调优.最后讲述了与 JVM 密切相 关的 Java GC 机制.
一本非常好的详细介绍java虚拟机实现原理及详细介绍的的好书 有兴趣了解JVM底层知识的看看,太大了,分三部分,都下了才能解压
一本非常好的详细介绍java虚拟机实现原理及详细介绍的的好书 有兴趣了解JVM底层知识的看看,太大了,分三部分,都下了才能解压
如果你对java虚拟机感兴趣,并且从未接触过JVM,那么这本书将带你走入JVM世界。
详细介绍java 虚拟机的相关参数设置和作用
JVM 深入JVM JVM详解 JVM知识点 java虚拟机 深入java虚拟机
一本非常好的详细介绍java虚拟机实现原理及详细介绍的的好书 有兴趣了解JVM底层知识的看看,太大了,分三部分,都下了才能解压
Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。它的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作...
主要介绍了Java虚拟机JVM性能优化(三):垃圾收集详解,本文讲解了众多的JVM垃圾收集器知识点,需要的朋友可以参考下
2015-09-12-Java虚拟机详解----JVM常见问题总结。 博客链接:http://www.cnblogs.com/smyhvae/p/4810168.html
Java既可以被编译,又可以被解释。 Java的源代码(后缀名为.java)文件,通过编译器,被翻译城一种中间代码,...可以把Java字节码看作是运行在Java虚拟机(JVM)上的机器代码指令。 大学老师课堂讲解,内部资料,值得一看。
深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器
java虚拟机
第20节Java虚拟机-高性能Java虚拟机00:02:58分钟 | 第21节Java虚拟机-TaobaoVM00:03:06分钟 | 第22节Java内存区域-简介00:07:56分钟 | 第23节Java内存区域-Java虚拟机栈00:12:04分钟 | 第24节Java内存区域-程序...
而每个线程创建的时候,都会拥有自己的程序计数器和 Java栈,其中程序计数器中的值指向下一条即将被执行的指令,线程的Java栈则存储为该线程调用Java方法的状态;本地方法调用的状态被存储在本地方法栈,该方法栈...
JVM(Java虚拟机)是一个抽象的计算模型。这篇文章主要介绍了Java虚拟机(JVM)运行时的相关知识,需要的朋友可以参考下
本文档介绍了java虚拟机的一些基础,并对java虚拟机作了比较详细的介绍,适合入门