zoukankan      html  css  js  c++  java
  • Java高级之类结构的认识


            本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


    Java体系包括,各种版本的虚拟机,可执行文件,各种第三方类库,Java API类库,Java语言

    发展史:91年James Gosling博士带领开发出Oak,95年互联网兴起来变成Java,并正式改名,并提出“一次编译到处执行”的口号。96年1.0正式发布,代表技术有Java虚拟机,AWT和Applet-以前很喜欢的Swing开发套件;

    97年1.1,代表技术有Jar文件格式、JDBC、JavaBeans、RMI、内部类、反射等

    98年1.2,拆分三个方向,就是J2ME,J2EE,J2SE 99年正式使用HotSpot,代表技术JIT、Collections集合类等

    2000年1.3,代表技术有数学运算、TimeApi、JNDI(正式应用)等,此后2年发布一次

    2002年1.4,走向成熟,正则表达式、XML解析器等出现

    2004年1.5,自动装箱、泛型、注解、枚举、可变长参数、循环等语法

    2006年1.6,提供动态语言支持、编译API和HTTP服务器API,对锁、同步、垃圾回收、类加载做了大量优化

    2009年1.7,由于涉及sun收购,之后的发布节奏也被打乱,提供新的G1收集器、加强对非JAVA语言的调用、升级类加载架构

    2012年1.8,支持接口有默认实现方法、支持Lamda表达式(android studio已支持)、TimerAPI的全新优化。


    Java的类结构是对变量,各种访问标记,接口和继承,同步、枚举,注解,内部类,异常、方法等的组合


    类文件是以8个字节为基础单位的二进制流


    类文件和图片都有魔数,用来标识它可以被虚拟机接受,即0xCafeBabe-全大写,只是为了方便大家记忆;在很多地方都有应用,因为文件后缀名可以改变,而它不能改变。


    Java类文件的前4位代表它是否能被虚拟机接受,之后是版本号,5和6代表次版本号,7和8代表主版本号

    紧接下来的是常量,大概有11种表结构,除了常见的String,Integer,Float,Double,Long以外,还有Class,Utf-8,Field,Method,InterfaceMethod,NameAndType类型,数量不确定


    接着是访问标志有8种,public,final,abstract,interface,super,enum,annotation,synthetic(非用户代码产生的类)


    接着是“继承”索引,this索引和super索引,除Object以外,其他索引值均不为0,代表有父类;索引集合描述这个类实现了哪些接口,从左到右按顺序排列,有几个计数器值为几


    再接下来是字段表集合,描述所有的变量(如作用范围-public,并变性-final,并发可见-volatile等)和返回值(基本数据类型和类),基本数据类型的全限定名,开头都是其英文大写,如'[()V; '和'[[Ljava/lang/String';前者代表一个空返回值,后者代表一个String二维数组,类都以L开头作表示;全限定名可以理解为对象的地址。


    接下来到方法表集合了,跟字段表一样,但某些访问控制答不能修饰方法,如volatile和transient关键字,方法名加尖括号表示,如<init>-指实例构造器,<cinit>-指类构造器,编译后的代码存在一个"Code"的属性里

    属性表,类、方法体、常量表中都有属性表

    1、Code属性指编译后的字节码,还有它的长度,栈的最大深度,最大存储空间,一个方法编译后不允许超过65535个字节码指令,一个指令=1Slot=32位,这是最小的存储单位,而float和int都是32位;一般还可以分为源码和元数据(即对源码的描述,如类,字段,方法等)

    	public static int getFinally() {
    		int a = 1;
    		try {
    			a = 2;
    			return a;
    		} catch (Exception e) {
    			// TODO: handle exception
    			a = 3;
    			return a;
    		} finally {
    			a = 4;
    		}
    	}
    上面是用一段源码,来对字节码指令进行分析,很多人看见后,都很想对照自己的结果,准确答案是2

    跟你的结果是否一致,为什么是2而不是4呢?

    这段代码可以分为三层来分析:

    第一层如果try没有任何问题,则执行a=2 return a

    第二层,如果try出错,则执行finally,再执行catch语句,a=3 return a

    第三层,如果try无错,catch无错,而出现了其他error,则直接执行finally语句的a=4

    这个地方可以这样理想,按照正常的Java指令没有打乱的情况下,先执行try return时已经执行a的write方法,则finally中仅执行了a的assign方法,此时a已经为2。不懂变量加载过程的,可以查看:Java高级之内存模型分析

    2、Exceptions属性 列举出可检查出的异常如catch语句后和throws的异常

    3、LineNumberTable属性 描写源码行号与字节码行号的关系,即这段代码位于哪一行,用于异常抛出时定位

    4、LocalVariableTable属性 定义后别人引用,不会产生参数是arg0,arg1的情况

    5、SourceFile属性,用于记录Class源码文件名称,主要异常抛出时可以定位是哪个文件

    6、ConstantValue属性,通知虚拟机自动定义为静态变量,只能为基本数据类型和String类型

    7、InnerClasses属性 显然定义内部类的,数量位置等

    8、Deprecated及Synthetic 前者是定义废弃类,方法,变量等,后者指非源码产生由编译器自动加的东西。


    Class文件是虚拟机解释的入口,了解其内部结构,有助于对代码进行分析定位错误,以及热加载等其他功能的理解。


    以下是拓展知识


    1位=1bit 最小的计算机单位,指0和1

    byte=8bit 字节 取值范围 -128到127 记忆技巧 2^字节次方

    char =2byte Unicode

    short=2byte -2^15到2^15-1

    int =4byte -2^31到2^31-1

    float=4byte

    long=8byte -2^63到2^63-1

    double=8byte  

    boolean 无意义

    一个汉字是2位,一个英文字母1位

    虚拟机的存存储区域,一般常说的有栈和堆,栈放指针和基本数据类型,而堆放对象,还有一种需要熟悉的是常量存储,就是存代码内部(方法里的);还有两种拓展了解:寄存器位于处理器内部,极少,处理极快;非RAM存储,如持久化对象和流对象,特指数据流传输和硬盘对象。除了常量存储存在只读存储器(ROM-Only)和寄存器,其他都存在随机访问存储器(RAM-Acess)里。

    位操作介绍四种,位与(&),位或(|),位否(~)和异或(^)

    位与,同为1则为1,否则为0

    位或,有一个1则为1,否同为0

    位否,1变0,0变1 计算方式~x=-(x+1)

    异或,不同则为1,相同则为0

    		int a = 0x010101;
    		int b = 0x110100;
    		System.out.println(a & b);
    		System.out.println("位于操作:"+0x010100);
    		System.out.println(a | b);
    		System.out.println("位或操作:"+0x110101);
    		System.out.println(a ^ b);
    		System.out.println("异或操作:"+0x100001);
    结果

    65792
    位于操作:65792
    1114369
    位或操作:1114369
    1048577
    异或操作:1048577
    Tips:负数操作 要先获得补码再操作,然后变源码+1操作

    另外一个例子:

    System.out.println((1 & 0) + "," + (1 & 1) + "," + (0 & 0));//两个为1才为1,否则为0
    System.out.println((1 | 0) + "," + (1 | 1) + "," + (0 | 0));//有一个为1则为1,否则为0
    System.out.println((1 ^ 0) + "," + (1 ^ 1) + "," + (0 ^ 0));//只有一个为1才为1,否则为0

    结果:

    0,1,0
    1,1,0
    1,0,0


    图片的大小=图片width*height*颜色深度

    格式有四种(A-Alpha不透明度 R-Red G-Green B-Blue)

    ALPHA_8格式  8位=1byte

    ARGB_4444格式 16位=4+4+4+4=2byte

    RGB_565格式 16位=5+6+5=2byte

    ARGB_8888格式 32位=8+8+8+8=4byte

    借用格式来压缩图片是一种不错的办法。

    以下是摘抄的图片魔数

    图像文件头
      1)1-2:(这里的数字代表的是"字",即两个字节,下同)图像文件头。0x4d42='BM',表示是Windows支持的BMP格式。(注意:查ascii表B 0x42,M0x4d,bfType 为两个字节,B为low字节,M为high字节所以bfType=0x4D42,而不是0x424D,但注意)
      2)3-6:整个文件大小。4690 0000,为00009046h=36934。
      3)7-8:保留,必须设置为0。
      4)9-10:保留,必须设置为0。
      5)11-14:从文件开始到位图数据之间的偏移量(14+40+4*(2^biBitCount))。4600 0000,为00000046h=70,上面的文件头就是35字=70字节。

    位图信息头

      6)15-18:位图图信息头长度。
      7) 19-22:位图宽度,以像素为单位。8000 0000,为00000080h=128。
      8)23-26:位图高度,以像素为单位。9000 0000,为00000090h=144。
      9)27-28:位图的位面数,该值总是1。0100,为0001h=1。
      10)29-30:每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)。1000为0010h=16。
      11)31-34:压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)。RLE简单地说是采用像素数+像素值的方式进行压缩。T408采用的是位域存放方式,用两个字节表示一个像素,位域分配为r5b6g5。图中0300 0000为00000003h=3。
      12)35-38:用字节数表示的位图数据的大小,该数必须是4的倍数,数值上等于(≥位图宽度的最小的4的倍数)×位图高度×每个像素位数。0090 0000为00009000h=80×90×2h=36864。
      13)39-42:用象素/米表示的水平分辨率。A00F 0000为0000 0FA0h=4000。
      14)43-46:用象素/米表示的垂直分辨率。A00F 0000为0000 0FA0h=4000。
      15)47-50:位图使用的颜色索引数。设为0的话,则说明使用所有调色板项。
      16)51-54:对图象显示有重要影响的颜色索引的数目。如果是0,表示都重要。 

    Java中的switch语句支持整型和枚举,整型包括byte,short,int,char



  • 相关阅读:
    从 i++ 和 ++i 说起局部变量表和操作数栈
    数据库连接情况查询相关sql语句
    db2相关语句
    BeanUtils源码详解
    Spring注解驱动开发之AOP
    Spring注解驱动开发之IOC
    正则表达式
    linux特殊符号
    linux下面如何让一个软件/命令开机自启动
    linux文件属性
  • 原文地址:https://www.cnblogs.com/fengju/p/6174403.html
Copyright © 2011-2022 走看看