??xml version="1.0" encoding="utf-8" standalone="yes"?>在线视频一区二区三区,国内精品久久久久影院薰衣草 ,夜夜精品视频一区二区http://www.aygfsteel.com/DLevin/category/48888.htmlIn general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatrazh-cnSat, 05 Sep 2015 03:18:43 GMTSat, 05 Sep 2015 03:18:43 GMT60Java字节码(.class文gQ的代码解析http://www.aygfsteel.com/DLevin/archive/2011/09/13/358498.htmlDLevinDLevinMon, 12 Sep 2011 16:05:00 GMThttp://www.aygfsteel.com/DLevin/archive/2011/09/13/358498.htmlhttp://www.aygfsteel.com/DLevin/comments/358498.htmlhttp://www.aygfsteel.com/DLevin/archive/2011/09/13/358498.html#Feedback1http://www.aygfsteel.com/DLevin/comments/commentRss/358498.htmlhttp://www.aygfsteel.com/DLevin/services/trackbacks/358498.html

Java二进制指令代码以以下格式紧凑排列Q?/span>opcode占一个字节)Q?/span>

opcode operand*

除了tableswitch?/span>lookupswitch两条指o中间存在填充字节以外Q其他指令都没有填充字节Q即使在两条指o之间也没有。因而在d指o的时候,要根据指令的定义d?/span> 

通过对上?/span>Java指o集的分析可以知道Q?/span>Java指o集中很大一部分没有操作敎ͼ因而对q部分指令,只需要读取一个字节的操作码,操作码映射成助记符卛_?/span> 

而对其他带操作数的指令,则需要根据不同类型分析(׃apache中的bcelQ?/span>Binary Code Engineering LibraryQ对字节码的支持Q操作码和助记符的映可以用com.sun.org.apache.bcel.internal.Constats中提供的映射表数l来完成Q?/span>

1.       处理两条Ҏ的指?/span>tableswitch?/span>lookupswitch指o?/span>

对这两条指oQ首先都要去掉填充字W以?/span>defaultbyte1索引h字对齐的?/span>

    private static void make4ByteAlignment(ByteSequence codes) {

       int usedBytes = codes.getIndex() % 4;

       int paddingBytes = (usedBytes == 0) ? 0 : 4 - usedBytes;

       for(int i = 0;i < paddingBytes;i++) {

           codes.readByte();

       }

}

?/span>tableswitch指oQ读?/span>defaultoffset|最项的|最大项的g及在最项和最大项之间每一的offset倹{ƈ且将d到的offset值和当前指o的基地址相加Q?/span>

           int defaultOffset1 = baseOffset + codes.readInt();

           builder.append("\tdefault = #" + defaultOffset1);

           int low = codes.readInt();

           int high = codes.readInt();

           int npair1 = high - low + 1;

           builder.append(", npairs = " + npair1 + "\n");

           for(int i = low;i <= high;i++) {

              int match = i;

              offset = baseOffset + codes.readInt();

              builder.append(String.format("\tcase %d : #%d\n", match, offset));

        }

 

?/span>lookupswitch指oQ读?/span>defaultoffset|键值对数|npairsQ,以及npairs对的键值对Q将得到?/span>offset值和当前指o的基地址相加Q?/span>

           int defaultOffset2 = baseOffset + codes.readInt();

           builder.append("\tdefault = #" + defaultOffset2);

           int npairs2 = codes.readInt();

           builder.append(", npairs = " + npairs2 + "\n");

           for(int i = 0;i < npairs2;i++) {

              int match = codes.readInt();

              offset = baseOffset + codes.readInt();

              builder.append(String.format("\tcase %d : #%d\n", match, offset));

        }

 

2.       所有条件蟩转指令都有两个字节的偏移量操作数Q?/span>if<cond>, if_icmp<cond>, ifnull, ifnonnull, if_acmp<cond>Q。无条g跌{指ogoto和子例程跌{指ojsr也都是两个字节的偏移量作为操作数?/span>

offset = baseOffset + codes.readShort();

builder.append(String.format("\t\t#%d\n", offset));

 

3.       对宽偏移量的跌{指ogoto_w和子例程跌{指ojsr_w的操作数是四个字节的偏移量?/span>

offset = baseOffset + codes.readInt();

builder.append(String.format("\t\t#%d\n", offset));

 

4.       wide指oQ则l箋d下一条指令,q将wide参数讄?/span>true?/span>

byteCodeToString(codes, pool, verbose, true);

 

5.       q有一些指令g一个字节的局部变量烦引号作ؓ操作数的Q如果有wide修饰Q则用两个字节作为操作数Q代表局部变量烦引号。这L指o有:aload, iload, fload, lload, dload, astore, istore, fstore, lstore, dstore, ret?/span>

if(wide) {

    index = codes.readUnsignedShort();

} else {

    index = codes.readUnsignedByte();

}

builder.append(String.format("\t\t%%%d\n", index));

6.       iinc指oQ以一个字节的局部变量烦引号和一个自q帔R作ؓ参数Q如果以wide修饰Q则该指令的局部变量烦引号和常量都占两个字节?/span>

    if(wide) {

       index = codes.readUnsignedShort();

       constValue = codes.readShort();

    } else {

       index = codes.readUnsignedByte();

       constValue = codes.readByte();

    }

builder.append(String.format("\t\t%d %d\n", index, constValue));

 

7.       对象操作指oQ它们的操作数都是常量池中的索引Q长度ؓ两个字节。指?/span>CONSTANT_Class_infocd的结构,q些指o?/span>new, checkcast, instanceof, anewarray?/span>

index = codes.readUnsignedShort();

builder.append("\t\t" + pool.getClassInfo(index).toInstructionString(verbose) + "\n");

 

8.       所有字D|作指令,它们的操作数都是帔R池中的烦引,长度Z个字节。指?/span>CONSTANT_Fieldref_infocdl构Q这些指令有getfield, putfield, getstatic, putstatic?/span>

index = codes.readUnsignedShort();

builder.append("\t\t" + pool.getFieldRefInfo(index).toInstructionString(verbose) + "\n");

 

9.       非接口方法调用指令,也都是以两个字节的烦引号作ؓ操作敎ͼ指向帔R池中?/span>CONSTANT_Methodref_infocdl构Q这些指令有invokespecial, invokevirtual, invokestatic?/span>

index = codes.readUnsignedShort();

builder.append("\t\t" + pool.getMethodRefInfo(index).toInstructionString(verbose) + "\n");

 

10.   接口Ҏ调用指oinvokeinterfaceQ它有四个字节的操作敎ͼ前两个字节ؓ帔R池的索引P指向CONSTANT_InterfaceMethodref_infocdQ第三个字节?/span>countQ表C参数的字节敎ͼ最后一个字节ؓ0倹{?/span>

index = codes.readUnsignedShort();

int nargs = codes.readUnsignedByte(); //Historical, redundant

builder.append("\t\t" + pool.getInterfaceMethodRefInfo(index).toInstructionString(verbose));

builder.append(" : " + nargs + "\n");

codes.readUnsignedByte(); //reserved should be zero

 

11.   基本cd的数l创建指?/span>newarrayQ它的操作数Z个字节的cd标识?/span>

String type = Constants.TYPE_NAMES[codes.readByte()];

builder.append(String.format("\t\t(%s)\n", type));

 

12.   多维数组的创建指?/span>multianewarrayQ它有三个字节的操作敎ͼ前两个字节ؓ索引P指向CONSTANT_Class_infocdQ表C数l的cdQ最后一个字节指定数l的l度?/span>

index = codes.readUnsignedShort();

int dimensions = codes.readUnsignedByte();

builder.append(String.format("\t\t%s (%d)\n", pool.getClassInfo(index).getName(), dimensions));

 

13.   帔R入栈指oldcQ以一个字节的索引号作为参敎ͼ指向CONSTANT_Integer_info?/span>CONSTANT_Float_info?/span>CONSTANT_String_info?/span>CONSTANT_Class_infocdQ表C入栈的常量|intcd倹{?/span>floatcd倹{?/span>String引用cd值或对象引用cd|?/span>

index = codes.readUnsignedByte();

builder.append("\t\t" + pool.getPoolItem(index).toInstructionString(verbose) + "\n");

 

14.   宽烦引的帔R入栈指oldc_wQ以两个字节的烦引号作ؓ参数Q指?/span>CONSTANT_Integer_info?/span>CONSTANT_Float_info?/span>CONSTANT_String_info?/span>CONSTANT_Class_infocdQ表C入栈的常量|intcd倹{?/span>floatcd倹{?/span>String引用cd值或对象引用cd|?/span>

index = codes.readUnsignedShort();

builder.append("\t\t" + pool.getPoolItem(index).toInstructionString(verbose) + "\n");

 

15.   宽烦引的帔R入栈指oldc2_wQ以两个字节的烦引号作ؓ参数Q指?/span>CONSTANT_Long_info?/span>CONSTANT_Double_infocdQ表C入栈的常量|longcd倹{?/span>doublecd|?/span>

index = codes.readUnsignedShort();

builder.append("\t\t" + pool.getPoolItem(index).toInstructionString(verbose) + "\n");

 

16.   bipush指oQ以一个字节的帔R作ؓ操作数?/span>

byte constByte = codes.readByte();

builder.append(“\t” + constByte);

 

17.   sipush指oQ以两个字节的常量作为操作数?/span>

short constShort = codes.readShort();

builder.append(“\t” + constShort);

 

以上q有一些没有完成的代码Q包括字D(ҎQ的{֐和描q符没有解析Q有一些解析的格式q需要调整等。不怎么PM的结构就是这样了Q其它的都是l节问题Q这里不讨论了?/span> 

参见bcel目?/span>org.apache.bcel.classfile.Utilityc?

2010q?0??/span>



DLevin 2011-09-13 00:05 发表评论
]]>
Java二进制指令代码解?/title><link>http://www.aygfsteel.com/DLevin/archive/2011/09/13/358497.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 12 Sep 2011 16:03:00 GMT</pubDate><guid>http://www.aygfsteel.com/DLevin/archive/2011/09/13/358497.html</guid><wfw:comment>http://www.aygfsteel.com/DLevin/comments/358497.html</wfw:comment><comments>http://www.aygfsteel.com/DLevin/archive/2011/09/13/358497.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.aygfsteel.com/DLevin/comments/commentRss/358497.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/DLevin/services/trackbacks/358497.html</trackback:ping><description><![CDATA[     摘要: 注Q去q在看《深入解析JVM》书的时候做的一些记录,同时参考了《Java虚拟范》。只是对指o的一些列举,加入了一些自q理解。可以用来查询? Java二进制指令代码解?Java源码在运行之前都要编译成为字节码格式Q如.class文gQ,然后由ClassLoader字节码载入q行。在字节码文件中Q指令代码只是其中的一部分Q里面还记录了字节码文g的编译版本、常量池、访问权限、所有成?..  <a href='http://www.aygfsteel.com/DLevin/archive/2011/09/13/358497.html'>阅读全文</a><img src ="http://www.aygfsteel.com/DLevin/aggbug/358497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/DLevin/" target="_blank">DLevin</a> 2011-09-13 00:03 <a href="http://www.aygfsteel.com/DLevin/archive/2011/09/13/358497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java字节码(.class文gQ格式详解(三)http://www.aygfsteel.com/DLevin/archive/2011/09/05/358035.htmlDLevinDLevinMon, 05 Sep 2011 15:38:00 GMThttp://www.aygfsteel.com/DLevin/archive/2011/09/05/358035.htmlhttp://www.aygfsteel.com/DLevin/comments/358035.htmlhttp://www.aygfsteel.com/DLevin/archive/2011/09/05/358035.html#Feedback3http://www.aygfsteel.com/DLevin/comments/commentRss/358035.htmlhttp://www.aygfsteel.com/DLevin/services/trackbacks/358035.html阅读全文

DLevin 2011-09-05 23:38 发表评论
]]>
Java字节码(.class文gQ格式详解(二)http://www.aygfsteel.com/DLevin/archive/2011/09/05/358034.htmlDLevinDLevinMon, 05 Sep 2011 15:33:00 GMThttp://www.aygfsteel.com/DLevin/archive/2011/09/05/358034.htmlhttp://www.aygfsteel.com/DLevin/comments/358034.htmlhttp://www.aygfsteel.com/DLevin/archive/2011/09/05/358034.html#Feedback0http://www.aygfsteel.com/DLevin/comments/commentRss/358034.htmlhttp://www.aygfsteel.com/DLevin/services/trackbacks/358034.html阅读全文

DLevin 2011-09-05 23:33 发表评论
]]>
Java字节码(.class文gQ格式详解(一Q?/title><link>http://www.aygfsteel.com/DLevin/archive/2011/09/05/358033.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 05 Sep 2011 15:24:00 GMT</pubDate><guid>http://www.aygfsteel.com/DLevin/archive/2011/09/05/358033.html</guid><wfw:comment>http://www.aygfsteel.com/DLevin/comments/358033.html</wfw:comment><comments>http://www.aygfsteel.com/DLevin/archive/2011/09/05/358033.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.aygfsteel.com/DLevin/comments/commentRss/358033.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/DLevin/services/trackbacks/358033.html</trackback:ping><description><![CDATA[     摘要: 介Q去q在诅R深入解析JVM》的时候写的,记得当时q想着用自q代码解析字节码的Q最后只完成了一部分。现在都不知道还有没有保留着Q貌似Apache有现成的BCEL工程可以做这件事。当时也只是Z学习。这份资料主要参考《深入解析JVM》和《Java虚拟范》貌似是1.2版本的,整理出来的。里面包含了一些自q理解和用实际代码的测试。有兴趣的童鞋可以研I研I。嘿ѝ要有错误也希望能ؓ弟指点出来Q?..  <a href='http://www.aygfsteel.com/DLevin/archive/2011/09/05/358033.html'>阅读全文</a><img src ="http://www.aygfsteel.com/DLevin/aggbug/358033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/DLevin/" target="_blank">DLevin</a> 2011-09-05 23:24 <a href="http://www.aygfsteel.com/DLevin/archive/2011/09/05/358033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java虚拟机内部体pȝ构(摘记Q待完善Q?)http://www.aygfsteel.com/DLevin/archive/2011/09/05/358032.htmlDLevinDLevinMon, 05 Sep 2011 15:20:00 GMThttp://www.aygfsteel.com/DLevin/archive/2011/09/05/358032.htmlhttp://www.aygfsteel.com/DLevin/comments/358032.htmlhttp://www.aygfsteel.com/DLevin/archive/2011/09/05/358032.html#Feedback0http://www.aygfsteel.com/DLevin/comments/commentRss/358032.htmlhttp://www.aygfsteel.com/DLevin/services/trackbacks/358032.html

Java虚拟Z内部pȝ构包?/span>class文g、类装蝲子系l、运行时数据区、之行引擎、本地方法调用结构,其中q行时数据区包括Ҏ区、堆?/span>Java栈、程序计数器、本地方法栈{。具体结构如下图所C(摘自Inside Java Virtual MachineQ:


 

1.       class文g

?/span>Java中,所有源文g都编译成二进制的字节码,然后p拟机装蝲q行。一般这L字节码是?/span>class文g的Ş式存在。在q行Ӟ?/span>ClassLoaderc(System ClassLoader or User-defined ClassLoaderQ找到对应的class文gQ读取其中的字节码,然后交由虚拟析运行?/span>

?/span>class文g中,包含了定义一个类或接口的所有信息,包括cd、访问权限、父cd、承的所有接口、所有字Dc所有方法、方法中的代码、属性等信息Qƈ且每?/span>class文g的开头还包含了魔术值和版本信息Q魔术值用以标识当前的字节码是合法的字节码Q版本表C生成当前字节码的编译器版本Q从而虚拟机L其版本而做特定处理Q如果对于虚拟机不支持的字节码版本号拒绝加蝲?/span>

?/span>class文g中,很多信息都是以字W串的Ş式存放,比如对外部类成员或方法的引用Q这些字W串信息在链接的时候由虚拟析。每?/span>Javac,不管是包成员c还是内部类都会生成一个单独的class文gQ因?/span>class文g是相对独立的。详l信息参?/span>class文g格式?/span>

 

2.       c装载子pȝ

c装载子pȝ负责查找class文gQ读取字节码Q做部分单的验,如魔数是否正,版本是否受支持,各种数据格式是否正确{。部分解析后的字节码数据存放到方法区中,最后创建字节码代表的类或接口的Class实例?/span>

?/span>Java中,c装载系l是通过ClassLoader来完成的。虚拟机规范中,定义了启动类装蝲器和用于定义c装载器。在sun提供的虚拟机中,包括了启动类装蝲器、扩展类装蝲器、系l类装蝲器、用户定义类装蝲器。他们以父子铄方式l织在一赗除了启动类装蝲器,其他的装载器都是ClassLoader的子cR?/span>ClassLoader定义了一些方法可以帮助用户定义自qc装载器Q如defineClass{。详情参?/span>Java中的ClassLoader?/span>

 

如何卸蝲cL据?Q第七章Q?/span>

 

3.       q行时数据区

q行时数据区保存了所有在q行时的信息。包括方法区?/span>Java栈、堆、程序寄存器、本地方法栈{。其中方法区和堆只在虚拟Z保存一份实例,因而需要处理多U程的同步问题;Java栈、程序寄存器是每个线E中有单独的实例Q因而对不同的线E,他们的数据是U有的?/span>

 

3.1   Ҏ?/span>

ҎZ保存了读取的字节码信息(包括帔R池,静态方法和静态成员信息)、字节码代表?/span>Classcd例、一个指向加载它?/span>ClassLoader实例?/span>

JavaE序可以有两U方式来获取某个cȝClass实例Q?/span>

1.       Class.forName()Ҏ

2.       Object.getClass()Ҏ

通过Class实例获取和该cL接口相关的Q何信息。参?/span>Classcȝ定义?/span>

Q注Q对有启?/span>ClassLoader加蝲的类Q?/span>ClassҎ中的getClassLoaderҎq回nullQ?/span>

 

为加快执行速度Q可以在ҎZ引入Ҏ表机Ӟ记录能被外界调用的该cȝ实例ҎQ包括父cMl承下来的方法?strong>Q第八章详细介绍Q)

 

ҎZҎcd搜烦cM息,法Q散列、搜索树{?/span>

 

3.2   Java?/span>

虚拟Zؓ每个U程生成一?/span>Java栈,因而对不同的线E,栈内的数据都是私有的?/span>Java栈由栈l成Q?/span>Java栈的操作只有两种Q压入栈帧和弹出栈。线E中每个Ҏ的调用都会在Java栈压入一个栈帧;每次Ҏq回Q正常方法或抛异常返回)Q该Ҏ对应的栈帧都会从栈中弹出?/span>

 

3.2.1         

栈由操作数栈、局部变量区和栈帧数据组成。由?/span>Java中的指o是基于栈而设计的Q因而很多指令的默认操作数就是操作数栈中的数据。操作数栈用于保存指令的操作数和指o操作后的l果?/span>

局部变量区用于保存当前Ҏ的局部变量?/span>

栈数据区则保存当前栈的信息,如指向当前类帔R池的指针Q用于操作数为常量池索引的指令;q有一些和特定虚拟机实现相关的信息和调试信息?/span>

 

3.3   E序寄存?/span>

每个U程在执行时都会保存当前指o的下一条指令的地址Q以控制E序的之行流E?/span>

 

3.4   ?/span>

堆保存了E序在运行时的所有对象。在Java中,所有的对象都是保存在堆中的Q而外部通过对象的引用来讉K对象。由?/span>Java存在垃圾回收器,因?/span>Java对象可能被移动,以减内存碎片。其中一U实现可以很好的解决Ud对象而需要改变所有该对象的引用变量的技术,卛_堆分为句柄池和对象池。对象池中的对象保存了对象的真正内容Q而句柄池中的包含两个指针,一个指向对象,一个指向类数据。一个对象引用就是指向句柄的之战。这样当需要移动对象时Q只要改变句柄池中指向对象的指针值即可。然而这U设计是以牺牲速度ZLQ因hơ访问对象就要多l历一ơ指针定位?/span>

 

在某些垃圑֛收器实现中,对象需要额外的信息Q如果引用计数的垃圾攉器,需要ؓ每个对象记录引用计数信息Q而对另外有些机制Q则可能需要暂时保存某些数据。这些额外的数据可以保存在类中,也可以在记录在其他地斏V类似的q有同步机制中的数据和记录是否已l调用过finalizeҎ的信息?/span>

 

?/span>Java中有指o用于在内存中分配对象Q却没有昑ּ的指令来释放内存中的对象?/span>

 

3.5   本地Ҏ?/span>

?/span>JavaҎ调用本地Ҏ的时候,当前U程的程序寄存器是不定的倹{程序的执行也{向本地方法。本地方法可以正常返回,也可以抛出异常。抛出的异常会在调用该本地方法的指o中重新抛出?/span>

 

4.       执行引擎

每个用户U程Q即不包括垃圑֛收线E等Q都有一个执行引擎实例,用以执行字节码指令?/span>

 

5.       本地Ҏ接口

JavaE序可以通过本地Ҏ接口来调用本地方法?br />
                                                                                                                ?010-10-06



DLevin 2011-09-05 23:20 发表评论
]]>
վ֩ģ壺 | ˮ| | | Ϸ| Ԫı| | ʯ| ̨| ŷ| | | ҽ| ̺| | ϲ| ̨| ٺ| | | | | | | ǭ| | | | | żҸ| | Ҧ| | | | ³ɽ| | | Ͷ| ɽ| |