- 浏览: 322685 次
- 来自: ...
文章分类
最新评论
-
梦回秘蓝:
whichisnotuse 写道非也, 除非需要很执行一段代码 ...
什么情况需要 if (log.isDebugEnabled()) {} -
wupy:
一直while的话会不会太耗内存呢?
java socket 长连接 短连接 -
xy2401:
<type-mapping> <sql-t ...
hibernate tools oracle nvarchar2 被映射成Serializable -
xy2401:
xy2401 写道额,原来配置文件可以改啊。。。不过我已经生成 ...
hibernate tools oracle nvarchar2 被映射成Serializable -
郭玉成:
你好, 我已经找到原因了!
java 编译非文本形式的文件
http://blog.csdn.net/wjsfr/archive/2005/04/13/346189.aspx
本文首先介绍一下Java虚拟机的生存周期,然后大致介绍JVM的体系结构,最后对体系结构中的各个部分进行详细介绍。( 首先这里澄清两个概念:JVM实例和JVM执行引擎实例,JVM实例对应了一个独立运行的java程序,而JVM执行引擎实例则对应了属于用户运行程序的线程;也就是JVM实例是进程级别,而执行引擎是线程级别的。)
一、 JVM的生命周期
JVM实例的诞生:当启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点,既然如此,那么JVM如何知道是运行class A的main而不是运行class B的main呢?这就需要显式的告诉JVM类名,也就是我们平时运行java程序命令的由来,如java classA hello world,这里java是告诉os运行Sun java 2 SDK的java虚拟机,而classA则指出了运行JVM所需要的类名。
JVM实例的运行:main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,java程序也可以标明自己创建的线程是守护线程。JVM实例的消亡:当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出。
二、JVM的体系结构
粗略分来,JVM的内部体系结构分为三部分,分别是:类装载器(ClassLoader)子系统,运行时数据区,和执行引擎。 下面将先介绍类装载器,然后是执行引擎,最后是运行时数据区
1,类装载器,顾名思义,就是用来装载.class文件的。JVM的两种类装载器包括:启动类装载器和用户自定义类装载器,启动类装载器是JVM实现的一部分,用户自定义类装载器则是Java程序的一部分,必须是ClassLoader类的子类。(下面所述情况是针对Sun JDK1.2)
动类装载器:只在系统类(java API的类文件)的安装路径查找要装入的类
用户自定义类装载器:
系统类装载器:在JVM启动时创建,用来在CLASSPATH目录下查找要装入的类其他用户自定义类装载器:这里有必要先说一下ClassLoader类的几个方法,了解它们对于了解自定义类装载器如何装载.class文件至关重要。
protected final Class defineClass(String name, byte data[], int offset, int length)
protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain protectionDomain);
protected final Class findSystemClass(String name)
protected final void resolveClass(Class c)
defineClass用来将二进制class文件(新类型)导入到方法区,也就是这里指的类是用户自定义的类(也就是负责装载类)
findSystemClass通过类型的全限定名,先通过系统类装载器或者启动类装载器来装载,并返回Class对象。
ResolveClass: 让类装载器进行连接动作(包括验证,分配内存初始化,将类型中的符号引用解析为直接引用),这里涉及到java命名空间的问题,JVM保证被一个类装载器装载的类所引用的所有类都被这个类装载器装载,同一个类装载器装载的类之间可以相互访问,但是不同类装载器装载的类看不见对方,从而实现了有效的屏蔽。
2, 执行引擎:它或者在执行字节码,或者执行本地方法
要说执行引擎,就不得不的指令集,每一条指令包含一个单字节的操作码,后面跟0个或者多个操作数。
(一)指令集以栈为设计中心,而非以寄存器为中心这种指令集设计如何满足Java体系的要求:
平台无关性:以栈为中心使得在只有很少register的机器上实现java更便利compiler一般采用stack向连接优化器传递编译的中间结果,若指令集以stack为基础,则有利于运行时进行的优化工作与执行即时编译或者自适应优化的执行引擎结合,通俗的说就是使编译和运行用的数据结构统一,更有利于优化的开展。
网络移动性:class文件的紧凑性。
安全性:指令集中绝大部分操作码都指明了操作的类型。(在装载的时候使用数据流分析期进行一次性验证,而非在执行每条指令的时候进行验证,有利于提高执行速度)。
(二)执行技术
主要的执行技术有:解释,即时编译,自适应优化、芯片级直接执行其中解释属于第一代JVM,即时编译JIT属于第二代JVM,自适应优化(目前Sun的HotspotJVM采用这种技术)则吸取第一代JVM和第二代JVM的经验,采用两者结合的方式
自适应优化:开始对所有的代码都采取解释执行的方式,并监视代码执行情况,然后对那些经常调用的方法启动一个后台线程,将其编译为本地代码,并进行仔细优化。若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行。
3,运行时数据区:主要包括:方法区,堆,java栈,PC寄存器,本地方法栈
(1)方法区和堆由所有线程共享
堆:存放所有程序在运行时创建的对象
方法区:当JVM的类装载器加载.class文件,并进行解析,把解析的类型信息放入方法区。
(2)Java栈和PC寄存器由线程独享,在新线程创建时间里
(3)本地方法栈: 存储本地方法调用的状态
上边总体介绍了运行时数据区的主要内容,下边进行详细介绍,要介绍数据区,就不得不说明JVM中的数据类型。
JVM中的数据类型:JVM中基本的数据单元是word,而word的长度由JVM具体的实现者来决定
数据类型包括基本类型和引用类型,
(1)基本类型包括:数值类型(包括除boolean外的所有的java基本数据类型),boolean(在JVM中使用int来表示,0表示false,其他int值均表示true)和returnAddress(JVM的内部类型,用来实现finally子句)。
(2)引用类型包括:数组类型,类类型,接口类型
前边讲述了JVM中数据的表示,下面让我们输入到JVM的数据区
首先来看方法区:
上边已经提到,方法区主要用来存储JVM从class文件中提取的类型信息,那么类型信息是如何存储的呢?众所周知,Java使用的是大端序(big?endian:即低字节的数据存储在高位内存上,如对于1234,12是高位数据,34为低位数据,则java中的存储格式应该为12存在内存的低地址,34存在内存的高地址,x86中的存储格式与之相反)来存储数据,这实际上是在class文件中数据的存储格式,但是当数据倒入到方法区中时,JVM可以以任何方式来存储它。
类型信息:包括class的全限定名,class的直接父类,类类型还是接口类型,类的修饰符(public,等),所有直接父接口的列表,Class对象提供了访问这些信息的窗口(可通过Class.forName(“”)或instance.getClass()获得),下面是Class的方法,相信大家看了会恍然大悟,(原来如此J)
getName(), getSuperClass(), isInterface(), getInterfaces(), getClassLoader();
static变量作为类型信息的一部分保存
指向ClassLoader类的引用:在动态连接时装载该类中引用的其他类
指向Class类的引用:必然的,上边已述
该类型的常量池:包括直接常量(String,integer和float point常量)以及对其他类型、字段和方法的符号引用(注意:这里的常量池并不是普通意义上的存储常量的地方,这些符号引用可能是我们在编程中所接触到的变量),由于这些符号引用,使得常量池成为java程序动态连接中至关重要的部分
字段信息:普通意义上的类型中声明的字段
方法信息:类型中各个方法的信息
编译期常量:指用final声明或者用编译时已知的值初始化的类变量
class将所有的常量复制至其常量池或者其字节码流中。
方法表:一个数组,包括所有它的实例可能调用的实例方法的直接引用(包括从父类中继承来的)
除此之外,若某个类不是抽象和本地的,还要保存方法的字节码,操作数栈和该方法的栈帧,异常表。
举例:
class Lava{
private int speed = 5;
void flow(){}
class Volcano{
public static void main(String[] args){
Lava lava = new Lava();
lava.flow();
}
}
运行命令java Volcano;
(1)JVM找到Volcano.class倒入,并提取相应的类型信息到方法区。通过执行方法区中的字节码,JVM执行main()方法,(执行时会一直保存指向Vocano类的常量池的指针)
(2)Main()中第一条指令告诉JVM需为列在常量池第一项的类分配内存(此处再次说明了常量池并非只存储常量信息),然后JVM找到常量池的第一项,发现是对Lava类的符号引用,则检查方法区,看Lava类是否装载,结果是还未装载,则查找“Lava.class”,将类型信息写入方法区,并将方法区Lava类信息的指针来替换Volcano原常量池中的符号引用,即用直接引用来替换符号引用。
(3)JVM看到new关键字,准备为Lava分配内存,根据Volcano的常量池的第一项找到Lava在方法区的位置,并分析需要多少对空间,确定后,在堆上分配空间,并将speed变量初始为0,并将lava对象的引用压到栈中
(4)调用lava的flow()方法
好了,大致了解了方法区的内容后,让我们来看看堆
java对象的堆实现:
java对象主要由实例变量(包括自己所属的类和其父类声明的)以及指向方法区中类数据的指针,指向方法表的指针,对象锁(非必需), 等待集合(非必需),GC相关的数据(非必需)(主要视GC算法而定,如对于标记并清除算法,需要标记对象是否被引用,以及是否已调用finalize()方法)。
那么为什么java对象中要有指向类数据的指针呢?我们从几个方面来考虑
首先:当程序中将一个对象引用转为另一个类型时,如何检查转换是否允许?需用到类数据
其次:动态绑定时,并不是需要引用类型,而是需要运行时类型,
这里的迷惑是:为什么类数据中保存的是实际类型,而非引用类型?这个问题先留下来,我想在后续的读书笔记中应该能明白
指向方法表的指针:这里和C++的VTBL是类似的,有利于提高方法调用的效率
对象锁:用来实现多个线程对共享数据的互斥访问
等待集合:用来让多个线程为完成共同目标而协调功过。(注意Object类中的wait(),notify(),notifyAll()方法)。
Java数组的堆实现:数组也拥有一个和他们的类相关联的Class实例,具有相同dimension和type的数组是同一个类的实例。数组类名的表示:如[[Ljava/lang/Object 表示Object[][],[I表示int[],[[[B表示byte[][][]
至此,堆已大致介绍完毕,下面来介绍程序计数器和java栈
程序计数器:为每个线程独有,在线程启动时创建,
若thread执行java方法,则PC保存下一条执行指令的地址。
若thread执行native方法,则Pc的值为undefined
Java栈:java栈以帧为单位保存线程的运行状态,java栈只有两种操作,帧的压栈和出栈。
每个帧代表一个方法,java方法有两种返回方式,return和抛出异常,两种方式都会导致该方法对应的帧出栈和释放内存。
帧的组成:局部变量区(包括方法参数和局部变量,对于instance方法,还要首先保存this类型,其中方法参数按照声明顺序严格放置,局部变量可以任意放置),操作数栈,帧数据区(用来帮助支持常量池的解析,正常方法返回和异常处理)。
本地方法栈:依赖于本地方法的实现,如某个JVM实现的本地方法借口使用C连接模型,则本地方法栈就是C栈,可以说某线程在调用本地方法时,就进入了一个不受JVM限制的领域,也就是JVM可以利用本地方法来动态扩展本身。
发表评论
-
maven3的superpom换地方了
2011-06-17 16:00 1336路径是: maven-model-builder-3.0.3 ... -
eclipse 文件本地历史比较功能丢失
2010-09-07 19:01 2164如题,原来是我把该功能关闭了,在“首选项-capabiliti ... -
hibernate criteria like expression for Long
2010-05-13 18:11 1447https://forum.hibernate.org/vie ... -
java.lang.ClassFormatError: Incompatible magic value 218762506 in class file
2010-05-07 19:12 5093http://bugs.sun.com/view_bug.do ... -
maven2 install-file 不能一条命令安装jar source javadoc
2010-03-19 16:56 1948http://old.nabble.com/Help-unde ... -
maven2 eclipse hibernate test 测试类查询不到数据
2010-01-27 13:21 1849使用maven2构建的eclipse工程,写的测试类在ecli ... -
hibernate tools oracle nvarchar2 被映射成Serializable
2010-01-15 18:29 2869http://opensource.atlassian.com ... -
maven2 eclipse buildpath resources 问题
2010-01-15 09:29 2025https://docs.sonatype.org/displ ... -
spring aop方式获取方法执行时间不准
2010-01-09 17:47 1186AspectJ不管采用哪种通知方式(Before ,After ... -
Criteria + Projection + LockMode causes a NPE
2010-01-05 17:20 1059http://opensource.atlassian.com ... -
Hibernate Criteria 关联查询
2009-12-31 16:40 1861http://www.blogjava.net/hilor/a ... -
jbpm-3.3.1.GA 在tomcat/jetty配置方法
2009-08-06 16:16 1202jbpm-3.3.1.GA 在tomcat/jetty配置方法 ... -
pojo ejb web Services
2008-07-30 21:33 1057ejb to web Services http://www- ... -
Java中 static/transient,final/volatile 说明
2008-07-03 11:14 1848http://hi.baidu.com/jxliaom/blo ... -
web服务器绑定0.0.0.0 和 127.0.0.1 的区别
2008-06-15 16:47 5498发现在局域网其他人的电脑上浏览我的电脑上的提供的WEB服务的时 ... -
怎样在Eclipse中使用debug调试程序?
2008-06-06 09:45 1672参见: http://hua6884858.iteye.co ... -
什么情况需要 if (log.isDebugEnabled()) {}
2008-05-07 18:34 8708在使用log4j,common-log这样的log框架时,发现 ... -
使用 CAS 在 Tomcat 中实现单点登录 - zt
2008-04-17 14:04 2982级别: 初级 张 涛 (zzhangt@cn.ibm.com) ... -
对多核环境中多线程(JVM)与多进程(LAMP)的比较 - zt
2008-04-17 10:13 6055PHP 3之后的主要语言开发者之一、Zend公司的创始人之一A ... -
什么是ETag - zt
2008-04-01 10:11 1237使用ETags减少Web应用带宽和负载http://www.i ...
相关推荐
首先,让我们深入理解Nginx的upstream模块。Nginx作为一款高性能的HTTP和反向代理服务器,经常用于负载均衡,将来自客户端的请求分发到后端的一组服务器上。upstream模块是实现这一功能的关键部分,它允许我们定义一...
此资源有两个文件,含 nginx-upstream-jvm-route 和 nginx 对应版本,都是tar.gz文件。 安装方法网上很多就不写了,亲测可用。 不用担心版本不匹配造成安装失败,再浪费积分去到处下载尝试的烦恼。 此资源有两个文件...
kotlinx-coroutines-io-jvm-0.1.1.jar
Moonbox(月光宝盒)是JVM-Sandbox生态下的,基于jvm-sandbox-repeater重新开发的一款流量回放平台产品。在jvm-sandbox-repeater基础上提供了更加丰富功能,同时便于线上部署和使用,更多对比参考。 使用场景 你...
jvm-npm, 适用于JVM的兼容CommonJS模块加载器 JVM上Javascript运行时中的NPM模块加载支持。 实现基于 http://nodejs.org/api/modules.html,应该完全兼容。 当然,不包括完整的node.js API,因此不要期望依赖于它的...
《深入JVM---JVM命令---...理解`invokespecial`的工作原理有助于我们更深入地理解JVM的运行机制,进而优化Java程序的性能和设计。在实际编程中,合理运用这些知识能帮助我们编写出更加高效、稳定和安全的代码。
使用JVM-SANDBOX时,需要了解JVM的类加载机制,理解字节码操作,以及熟悉Java动态代理相关的知识。配合`alibaba-jvm-sandbox-35eae8e`这样的库,开发者可以更高效地利用JVM-SANDBOX进行各种实时的AOP操作。 总的来...
赠送jar包:metrics-jvm-3.1.5.jar; 赠送原API文档:metrics-jvm-3.1.5-javadoc.jar; 赠送源代码:metrics-jvm-3.1.5-sources.jar; 赠送Maven依赖信息文件:metrics-jvm-3.1.5.pom; 包含翻译后的API文档:...
项目的源代码(如`jvm-sandbox-master`)包含详细的示例和文档,可以帮助开发者快速理解和使用。 总结来说,JVM-Sandbox是一个强大的工具,它利用JVM的特性实现了动态的AOP,为开发者提供了在不修改源码的情况下...
赠送jar包:metrics-jvm-3.1.5.jar; 赠送原API文档:metrics-jvm-3.1.5-javadoc.jar; 赠送源代码:metrics-jvm-3.1.5-sources.jar; 赠送Maven依赖信息文件:metrics-jvm-3.1.5.pom; 包含翻译后的API文档:...
标题 "nginx-upstream-jvm-route nginx共享Session" 涉及到的是在使用Nginx作为反向代理服务器时,如何实现多个Java应用服务器(通常指的是JVM实例)之间的Session共享。这通常在构建高可用性和负载均衡的Web服务...
《深入理解JVM-2Edition-类文件结构》是一份详细阐述Java虚拟机(JVM)如何处理类文件的文档。类文件是Java程序编译后的二进制表示,其结构直接影响了Java的平台无关性和语言无关性。下面将详细探讨类文件的各个组成...
1、java虚拟机的基本介绍。 2、字节码的执行 3、常用的jvm参数配置 4、算法和种类 5、gc参数配置 6、类加载器 7、性能监控工具 8、jvm堆栈分析
"JAVA进阶高级jav"进一步指出这份资料主要面向已经有一定基础的Java开发者,旨在帮助他们深入理解JVM的工作原理,提升到更高级的Java开发水平。 【压缩包子文件的文件名称列表】"尚宋-硅红-谷康-JVM-ppt"可能是作者...
虽然`jvm-mon`提供了基本的JVM监控功能,但更复杂的性能问题可能需要结合其他专业工具,如JProfiler、VisualVM、YourKit等,它们提供更深入的分析和故障排查能力,如方法调用时间线、内存分配跟踪、线程栈深度等。...
nginx_upstream_jvm_route 是一个 Nginx 的扩展模块,用来实现基于 Cookie 的 Session Sticky 的功能。 安装方法(进入Nginx源码目录): #patch -p0 < /path/to/this/directory/jvm_route.patch # ./configure -...
首先,让我们了解一下Nginx的Upstream模块。Upstream模块允许Nginx将接收到的请求转发到一组后端服务器,可以根据配置的策略进行负载均衡,比如轮询、最少连接数等。通过这种方式,Nginx能够分散用户请求,提高系统...
在IT领域,优化Java应用程序的性能是至关重要的,而JVM(Java虚拟机)作为Java程序运行的基础,其内部运作机制的了解和调优对于提升效率至关重要。"jvm-profiler"是一个开源项目,专为Java开发者设计,用于对JVM进行...
是生态体系下的重要模块,它具备了JVM-Sandbox的所有特点,插件式设计便于快速适配各种中间件,封装请求录制/回放基础协议,也提供了通用可扩展的各种丰富API。 目标人群 - 面向测试开发工程师 线上有个用户请求一直...