Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 838|回复: 0

Java分布式应用学习笔记再谈JVM

[复制链接]

该用户从未签到

发表于 2011-8-3 23:05:34 | 显示全部楼层 |阅读模式
1.  前言-为何要再谈JVM很多人认为,分布式java应用看上去好像和Java虚拟机没什么太多关注的东西,别说分布式系统了,就是一个单机JavaSE系统也不用将JVM学得透透的,有个JVM执行不就行了吗。据笔者的经验回答则是,在大型分布式系统,尤其是云计算服务平台,SAAS也好,PAAS也罢,要求编写的应用必须要高效,你就当你运行的是一个配置很小的机器上,要求资源比较苛刻。所以了解,甚至再学习JVM相关知识还是十分必要的。之前笔者写过一篇关于JVM加载类的文章http://www.cn-java.com/www1/?uid-709144-action-viewspace-itemid-101967。后来发现这些还是不够的,还是需要在总结一下JVM运行时的其他环节。对于我们开发分布式的Java系统是有一种潜移默化的作用,主要用于自己回顾用。2.  JVM结构JVM主要负责什么工作呢,首先它负责将我们编写的java文件编译成为class文件;第二它负责加载已有的class文件;第三它还负责class的执行;第四JVM还负责内存的分配与回收,这也是为什么大家在写代码的过程中不用手工写代码分配资源和强制回收资源了,有个强势的管家——JVM为您做了;JVM还要和底层操作系统接口进行交互完成多线程资源的同步、并发机制,所以为什么我们实现一个Runnable接口或者集成Thread就能完成多线程操作了,表面上看您除了编写一些特殊的类什么都没做,实际上是JVM为您默默做了那么多。Sun,哦,不,笔者老是改不了口,Oracle的Java规范JVM如下:Class文件被类加载器加载,JVM为其开辟内存空间,内存空间又分为四个大部分:方法区、堆区、栈区、本地方法栈区。JVM启动优先级比较小的线程来运行垃圾回收器,时刻监视并回收开辟的内存区域。
3.  JVM到底如何编译Java代码运行class文件需要将java文件编译成为class文件,JavaSDK如何编译的呢?javac将java源代码编译class过程如下:

1:分析输入到符号表:将java文件内容的字符串转变为关键字序列,之后生成一个类似于树状结构的内容,叫做抽象语法树。所谓输入到符号表的意思,就是将类中出现的符号输入类自身的符号表中等。所谓符号一般是指:父类、接口,因为要根据这些符号生成无参构造函数。2:处理注解阶段:在JDK1.5之前,JVM没有这个阶段,但是JDK1.5之后咱们在Java类文件中写的注解需要JVM来进行处理、加强,至于注解保留到何时才生效。之后根据抽象语法树中等等信息联系到一起,进行有效性判断,一些列的语义判断,校验,优化某些代码,之后就是我们看到的class文件。class中除了字节码,还包括了JVM执行class的相关信息:结构信息:class的文件格式版本号以及各部分的数量与大小。元数据:元数据代表类的继承关系、接口、声明信息、属性、方法声明信息、常量池信息。方法信息:包括字节码、异常处理表、局部变量区大小我们利用反编译工具反编译一下以前自己写过的class源码,是不是发现确实JDK编译此文件的时候和我们源代码有些许出入,那是它为我们做了优化。 4.  JVM到底如何执行Java代码JVM执行class文件有3种方式,第一是解释执行、第二是编译执行、第三就是反射执行。可能大家对于第三个反射执行更为熟悉,因为这也是对大家相对真真正正编代码体验过的,而前两者都是由JVM给咱做的,所以听上去就十分陌生。1):解析执行在JVM中解析执行专门执行那些执行频率不高的代码,解析执行内部原理十分类似于咱们学过的汇编语言,JVM用一些自己自定义的指令(汇编语言也有自己一些简单的指令),来完成既有代码的执行过程,说白了,到了最底层,面向对象还是要过程化的。通过4条常用指令完成对类的解析和执行。Invokestatic负责调用static方法,invokevirtual负责调用实例对象方法,invokeinterface对应的是调用接口方法,invokespecial负责private方法的调用以及编译源码后(就是class)生成的构造方法。
如下一段代码 Java代码

    [li]import java.io.UnsupportedEncodingException;    [li]   [li]public class UTest {    [li]   [li]    public static void main(String[] args) throws UnsupportedEncodingException {    [li]        String c = java.net.URLDecoder    [li]                .decode("%E4%BA%A7%E5%93%81%E6%8F%8F%E8%BF%B0%E5%9F%9F%E8%B6%8A%E7%95%8C","utf-8");    [li]        System.out.println(" " + c);    [li]    }    [li]   [li]}  [/li]

复制打印

    import java.io.UnsupportedEncodingException;   [/li]  [/li]public class UTest {   [/li]  [/li]    public static void main(String[] args) throws UnsupportedEncodingException {   [/li]        String c = java.net.URLDecoder   [/li]                .decode("%E4%BA%A7%E5%93%81%E6%8F%8F%E8%BF%B0%E5%9F%9F%E8%B6%8A%E7%95%8C","utf-8");   [/li]        System.out.println(" " + c);   [/li]    }   [/li]  [/li]}  [/li]

import java.io.UnsupportedEncodingException;public class UTest {    public static void main(String[] args) throws UnsupportedEncodingException {        String c = java.net.URLDecoder                .decode("%E4%BA%A7%E5%93%81%E6%8F%8F%E8%BF%B0%E5%9F%9F%E8%B6%8A%E7%95%8C","utf-8");        System.out.println(" " + c);    }}[/pre] 编译成class后,使用javap –c UTest看字节码内容 Java代码

    [li]Compiled from "UTest.java"   [li]public class UTest extends java.lang.Object{    [li]public UTest();    [li]  Code:    [li]   0:   aload_0//装载局部变量第一个值到操作数栈    [li]   1:   invokespecial   #8; //Method java/lang/Object."<init>")V//初始化构造器    [li]   4:   return   [li]   [li]public static void main(java.lang.String[])   throws java.io.UnsupportedEncoding    [li]Exception;    [li]  Code:    [li]   0: ldc     #19; //String %E4%BA%A7%E5%93%81%E6%8F%8F%E8%BF%B0%E5%9F%9F%E8%B    [li]6%8A%E7%95%8C//将字符串值装载到常量池中    [li]   2: ldc     #21; //String utf-8//将字符串值装载到常量池中    [li]   4: invokestatic    #23; //Method java/net/URLDecoder.decode:(Ljava/lang/Str    [li]ing;Ljava/lang/String;)Ljava/lang/String;    [li]//调用静态方法java.net.URLDecoder.decode    [li]   7:   astore_1//将操作数栈中栈顶的值弹出放入局部变量区    [li]   8: getstatic       #29; //Field java/lang/System.outjava/io/PrintStream;    [li]   11:  new     #35; //class java/lang/StringBuilder    [li]   14:  dup    [li]   15:  ldc     #37; //String    [li]   17:invokespecial  #39; //Method java/lang/StringBuilder."<init>":(Ljava/la    [li]ng/String;)V    [li]   20:  aload_1    [li]   21:invokevirtual  #42; //Method java/lang/StringBuilder.append:(Ljava/lang    [li]/String;)Ljava/lang/StringBuilder;    [li]   24:invokevirtual  #46; //Method java/lang/StringBuilder.toString:()Ljava/l    [li]ang/String;    [li]   27:invokevirtual  #50;//Method java/io/PrintStream.println:(Ljava/lang/St    [li]ring;)V    [li]   30:  return   [li]}  [/li]

复制打印

    Compiled from "UTest.java"  [/li]public class UTest extends java.lang.Object{   [/li]public UTest();   [/li]  Code:   [/li]   0:   aload_0//装载局部变量第一个值到操作数栈   [/li]   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V//初始化构造器   [/li]   4:   return  [/li]  [/li]public static void main(java.lang.String[])   throws java.io.UnsupportedEncoding   [/li]Exception;   [/li]  Code:   [/li]   0: ldc     #19; //String %E4%BA%A7%E5%93%81%E6%8F%8F%E8%BF%B0%E5%9F%9F%E8%B   [/li]6%8A%E7%95%8C//将字符串值装载到常量池中   [/li]   2: ldc     #21; //String utf-8//将字符串值装载到常量池中   [/li]   4: invokestatic    #23; //Method java/net/URLDecoder.decode:(Ljava/lang/Str   [/li]ing;Ljava/lang/String;)Ljava/lang/String;   [/li]//调用静态方法java.net.URLDecoder.decode   [/li]   7:   astore_1//将操作数栈中栈顶的值弹出放入局部变量区   [/li]   8: getstatic       #29; //Field java/lang/System.out:Ljava/io/PrintStream;   [/li]   11:  new     #35; //class java/lang/StringBuilder   [/li]   14:  dup   [/li]   15:  ldc     #37; //String   [/li]   17:invokespecial  #39; //Method java/lang/StringBuilder."<init>":(Ljava/la   [/li]ng/String;)V   [/li]   20:  aload_1   [/li]   21:invokevirtual  #42; //Method java/lang/StringBuilder.append:(Ljava/lang   [/li]/String;)Ljava/lang/StringBuilder;   [/li]   24:invokevirtual  #46; //Method java/lang/StringBuilder.toString:()Ljava/l   [/li]ang/String;   [/li]   27:invokevirtual  #50;//Method java/io/PrintStream.println:(Ljava/lang/St   [/li]ring;)V   [/li]   30:  return  [/li]}  [/li]

Compiled from "UTest.java"public class UTest extends java.lang.Object{public UTest();  Code:   0:   aload_0//装载局部变量第一个值到操作数栈   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V//初始化构造器   4:   returnpublic static void main(java.lang.String[])   throws java.io.UnsupportedEncodingException;  Code:   0: ldc     #19; //String %E4%BA%A7%E5%93%81%E6%8F%8F%E8%BF%B0%E5%9F%9F%E8%B6%8A%E7%95%8C//将字符串值装载到常量池中   2: ldc     #21; //String utf-8//将字符串值装载到常量池中   4: invokestatic    #23; //Method java/net/URLDecoder.decode:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;//调用静态方法java.net.URLDecoder.decode   7:   astore_1//将操作数栈中栈顶的值弹出放入局部变量区   8: getstatic       #29; //Field java/lang/System.out:Ljava/io/PrintStream;   11:  new     #35; //class java/lang/StringBuilder   14:  dup   15:  ldc     #37; //String   17:invokespecial  #39; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V   20:  aload_1   21:invokevirtual  #42; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   24:invokevirtual  #46; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   27:invokevirtual  #50;//Method java/io/PrintStream.println:(Ljava/lang/String;)V   30:  return}[/pre]估计大家都看烦了,习惯了面向对象思维的大家一看这种汇编似的语言确实头疼,耐不下心。如果不是搞JVM开发的,其实了解一下就可以,毕竟了解一下JVM运行原理,对于我们写代码,无异于又过了一层思考。 解释执行比较慢,但是呢,比较省资源,省内存,因为采用栈这种数据结构进行指令的收编和采集,运用,空间利用率可见是比较节俭的。
2):编译执行:
为了提升性能,JDK还可以编译执行,也叫做即时编译器,通常是对执行频率比较高的代码进行及时编译执行。编译执行牺牲了部分空间资源,换来的是优化了字节码的编译实际代码块,就是说我们编写的代码在JVM编译器看来是可优化的,所以它采用优化编译,将原先的代码进行一些调整,进而更好地利用JVM资源。编译执行那个主要分为2类,一个是客户端类型,属轻量级;一类是服务端类型,属于重量级。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-11 04:04 , Processed in 0.303421 second(s), 36 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表