Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
JVMÉîÈëѧϰ£ºJava½âÎöClassÎļþ¹ý³Ì½âÎö
 
À´Ô´£º51CTO ·¢²¼ÓÚ 2017-2-10
  1962  次浏览      32
 

ǰÑÔ

ÉíΪһ¸öjava³ÌÐòÔ±£¬ÔõôÄܲ»Á˽âJVMÄØ£¬ÌÈÈôÏëѧϰJVM£¬ÄǾÍÓÖ±ØÐëÒªÁ˽âClassÎļþ£¬ClassÖ®ÓÚÐéÄâ»ú£¬¾ÍÈçÓãÖ®ÓÚË®£¬ÐéÄâ»úÒòΪClass¶øÓÐÁËÉúÃü¡£¡¶ÉîÈëÀí½âjavaÐéÄâ»ú¡·Öл¨ÁËÒ»Õû¸öÕ½ÚÀ´½²½âClassÎļþ£¬¿ÉÊÇ¿´Íêºó£¬Ò»Ö±¶¼»¹ÊÇÃÔÃÔºýºý£¬Ëƶ®·Ç¶®¡£ÕýºÃǰ¶Îʱ¼ä¿´¼ûÒ»±¾ÊéºÜ²»´í£º¡¶×Ô¼º¶¯ÊÖдJavaÐéÄâ»ú¡·£¬×÷ÕßÀûÓÃgoÓïÑÔʵÏÖÁËÒ»¸ö¼òµ¥µÄJVM£¬ËäȻûÓÐÍêÕûʵÏÖJVMµÄËùÓй¦ÄÜ£¬µ«ÊǶÔÓÚһЩ¶ÔJVMÉÔ¸ÐÐËȤµÄÈËÀ´Ëµ£¬¿É¶ÁÐÔ»¹ÊǺܸߵġ£×÷Õß½²½âµÄºÜÏêϸ£¬Ã¿¸ö¹ý³Ì¶¼·ÖΪÁËÒ»Õ£¬ÆäÖÐÒ»²¿·Ö¾ÍÊǽ²½âÈçºÎ½âÎöClassÎļþ¡£

Õâ±¾Ê鲻̫ºñ£¬ºÜ¿ì¾Í¶ÁÍêÁË£¬¶ÁÍêºó£¬ÊÕ»ñÆÄ·á¡£µ«ÊÇÖ½ÉϵÃÀ´ÖÕ¾õdz£¬¾øÖª´ËÊÂÒª¹ªÐУ¬Îұ㳢ÊÔ×Å×Ô¼º½âÎöClassÎļþ¡£goÓïÑÔËäÈ»ºÜÓÅÐ㣬µ«ÊÇÖÕ¾¿²»ÊìÁ·£¬ÓÈÆäÊDz»Ì«Ï°¹ßÆä°ÑÀàÐÍ·ÅÔÚ±äÁ¿Ö®ºóµÄÓï·¨£¬»¹ÊÇÀÏÀÏʵʵÓÃjava°É¡£

»°²»¶à˵£¬ÏÈÌù³öÏîÄ¿µØÖ·:https://github.com/HalfStackDeveloper/ClassReader

ClassÎļþ

ʲôÊÇClassÎļþ£¿

javaÖ®ËùÒÔÄܹ»ÊµÏÖ¿çÆ½Ì¨£¬±ãÔÚÓÚÆä±àÒë½×¶Î²»Êǽ«´úÂëÖ±½Ó±àÒëΪƽ̨Ïà¹ØµÄ»úÆ÷ÓïÑÔ£¬¶øÊÇÏȱàÒë³É¶þ½øÖÆÐÎʽµÄjava×Ö½ÚÂ룬·ÅÔÚClassÎļþÖ®ÖУ¬ÐéÄâ»úÔÙ¼ÓÔØClassÎļþ£¬½âÎö³ö³ÌÐòÔËÐÐËùÐèµÄÄÚÈÝ¡£Ã¿¸öÀà¶¼»á±»±àÒë³ÉÒ»¸öµ¥¶ÀµÄclassÎļþ£¬ÄÚ²¿ÀàÒ²»á×÷Ϊһ¸ö¶ÀÁ¢µÄÀ࣬Éú³É×Ô¼ºµÄclass¡£

»ù±¾½á¹¹

Ëæ±ãÕÒµ½Ò»¸öclassÎļþ£¬ÓÃSublime Text´ò¿ªÊÇÕâÑùµÄ£º

ÊDz»ÊÇÒ»Á³ã±ƣ¬²»¹ýjavaÐéÄâ»ú¹æ·¶Öиø³öÁËclassÎļþµÄ»ù±¾¸ñʽ£¬Ö»Òª°´ÕÕÕâ¸ö¸ñʽȥ½âÎö¾Í¿ÉÒÔÁË£º

ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

ClassFileÖеÄ×Ö¶ÎÀàÐÍÓÐu1¡¢u2¡¢u4,ÕâÊÇʲôÀàÐÍÄØ£¿ÆäʵºÜ¼òµ¥£¬¾ÍÊÇ·Ö±ð±íʾ1¸ö×Ö½Ú£¬2¸ö×Ö½ÚºÍ4¸ö×Ö½Ú¡£

¿ªÍ·Ëĸö×Ö½ÚΪ£ºMagic£¬ÊÇÓÃÀ´Î¨Ò»±êʶÎļþ¸ñʽµÄ£¬Ò»°ã±»³Æ×÷magic number£¨Ä§Êý£©£¬ÕâÑùÐéÄâ»ú²ÅÄÜʶ±ð³öËù¼ÓÔØµÄÎļþÊÇ·ñÊÇclass¸ñʽ£¬classÎļþµÄħÊýΪcafebabe¡£²»Ö»ÊÇclassÎļþ£¬»ù±¾Éϴ󲿷ÖÎļþ¶¼ÓÐħÊý£¬ÓÃÀ´±êʶ×Ô¼ºµÄ¸ñʽ¡£

½ÓÏÂÀ´µÄ²¿·ÖÖ÷ÒªÊÇclassÎļþµÄһЩÐÅÏ¢£¬Èç³£Á¿³Ø¡¢Àà·ÃÎʱêÖ¾¡¢¸¸Àà¡¢½Ó¿ÚÐÅÏ¢¡¢×ֶΡ¢·½·¨µÈ£¬¾ßÌåµÄÐÅÏ¢¿É²Î¿¼¡¶JavaÐéÄâ»ú¹æ·¶¡·¡£

½âÎö

×Ö¶ÎÀàÐÍ

ÉÏÃæËµµ½ClassFileÖеÄ×Ö¶ÎÀàÐÍÓÐu1¡¢u2¡¢u4£¬·Ö±ð±íʾ1¸ö×Ö½Ú£¬2¸ö×Ö½ÚºÍ4¸ö×Ö½ÚµÄÎÞ·ûºÅÕûÊý¡£javaÖÐshort¡¢int¡¢long·Ö±ðΪ2¡¢4¡¢8¸ö×Ö½ÚµÄÓзûºÅÕûÊý£¬È¥µô·ûºÅ룬¸ÕºÃ¿ÉÒÔÓÃÀ´±íʾu1¡¢u2¡¢u4¡£

public class U1 {
public static short read(InputStream inputStream) {
byte[] bytes = new byte[1];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
short value = (short) (bytes[0] & 0xFF);
return value;
}
}

public class U2 {
public static int read(InputStream inputStream) {
byte[] bytes = new byte[2];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
int num = 0;
for (int i= 0; i < bytes.length; i++) {
num <<= 8;
num |= (bytes[i] & 0xff);
}
return num;
}
}

public class U4 {
public static long read(InputStream inputStream) {
byte[] bytes = new byte[4];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
long num = 0;
for (int i= 0; i < bytes.length; i++) {
num <<= 8;
num |= (bytes[i] & 0xff);
}
return num;
}
}

³£Á¿³Ø

¶¨ÒåºÃ×Ö¶ÎÀàÐͺó£¬ÎÒÃǾͿÉÒÔ¶ÁÈ¡classÎļþÁË£¬Ê×ÏÈÊǶÁȡħÊýÖ®ÀàµÄ»ù±¾ÐÅÏ¢£¬Õⲿ·ÖºÜ¼òµ¥£º

FileInputStream inputStream = new FileInputStream(file);
ClassFile classFile = new ClassFile();
classFile.magic = U4.read(inputStream);
classFile.minorVersion = U2.read(inputStream);
classFile.majorVersion = U2.read(inputStream);

Õⲿ·ÖÖ»ÊÇÈÈÈÈÉí£¬½ÓÏÂÀ´µÄ´óÍ·ÔÚÓÚ³£Á¿³Ø¡£½âÎö³£Á¿³ØÖ®Ç°£¬ÎÒÃÇÏÈÀ´½âÊÍһϳ£Á¿³ØÊÇʲô¡£

³£Á¿³Ø£¬¹ËÃû˼Ò壬´æ·Å³£Á¿µÄ×ÊÔ´³Ø£¬ÕâÀïµÄ³£Á¿Ö¸µÄÊÇ×ÖÃæÁ¿ºÍ·ûºÅÒýÓá£×ÖÃæÁ¿Ö¸µÄÊÇһЩ×Ö·û´®×ÊÔ´£¬¶ø·ûºÅÒýÓ÷ÖΪÈýÀࣺÀà·ûºÅÒýÓᢷ½·¨·ûºÅÒýÓúÍ×ֶηûºÅÒýÓá£Í¨¹ý½«×ÊÔ´·ÅÔÚ³£Á¿³ØÖУ¬ÆäËûÏî¾Í¿ÉÒÔÖ±½Ó¶¨Òå³É³£Á¿³ØÖеÄË÷ÒýÁË£¬±ÜÃâÁ˿ռäµÄÀË·Ñ£¬²»Ö»ÊÇclassÎļþ£¬Android¿ÉÖ´ÐÐÎļþdexÒ²ÊÇͬÑùÈç´Ë£¬½«×Ö·û´®×ÊÔ´µÈ·ÅÔÚDexDataÖУ¬ÆäËûÏîͨ¹ýË÷Òý¶¨Î»×ÊÔ´¡£javaÐéÄâ»ú¹æ·¶¸ø³öÁ˳£Á¿³ØÖÐÿһÏîµÄ¸ñʽ£º

cp_info {
u1 tag;
u1 info[];
}

ÉÏÃæµÄÕâ¸ö¸ñʽֻÊÇÒ»¸öͨÓøñʽ£¬³£Á¿³ØÖÐÕæÕý°üº¬µÄÊý¾ÝÓÐ14ÖÖ¸ñʽ£¬Ã¿ÖÖ¸ñʽµÄtagÖµ²»Í¬

ÓÉÓÚ¸ñʽ̫¶à£¬ÎÄÕÂÖÐÖ»Ìôѡһ²¿·Ö½²½â£º

ÕâÀïÊ×ÏȶÁÈ¡³£Á¿³ØµÄ´óС£¬³õʼ»¯³£Á¿³Ø£º

//½âÎö³£Á¿³Ø
int constant_pool_count = U2.read(inputStream);
ConstantPool constantPool = new ConstantPool(constant_pool_count);
constantPool.read(inputStream);

½ÓÏÂÀ´ÔÙÖð¸ö¶ÁȡÿÏîÄÚÈÝ£¬²¢´æ´¢µ½Êý×écpInfoÖУ¬ÕâÀïÐèҪעÒâµÄÊÇ£¬cpInfo[]ϱê´Ó1¿ªÊ¼£¬0ÎÞЧ£¬ÇÒÕæÕýµÄ³£Á¿³Ø´óСΪconstant_pool_count-1¡£

public class ConstantPool {
public int constant_pool_count;
public ConstantInfo[] cpInfo;

public ConstantPool(int count) {
constant_pool_count = count;
cpInfo = new ConstantInfo[constant_pool_count];
}

public void read(InputStream inputStream) {
for (int i = 1; i < constant_pool_count; i++) {
short tag = U1.read(inputStream);
ConstantInfo constantInfo = ConstantInfo.getConstantInfo(tag);
constantInfo.read(inputStream);
cpInfo[i] = constantInfo;
if (tag == ConstantInfo.CONSTANT_Double || tag == ConstantInfo.CONSTANT_Long) {
i++;
}
}
}
}

ÎÒÃÇÏÈÀ´¿´¿´CONSTANT_Utf8¸ñʽ£¬ÕâÒ»ÏîÀïÃæ´æ·ÅµÄÊÇMUTF-8±àÂëµÄ×Ö·û´®£º

CONSTANT_Utf8_info { 
u1 tag;
u2 length;
u1 bytes[length];
}

ÄÇôÈçºÎ¶ÁÈ¡ÕâÒ»ÏîÄØ£¿

public class ConstantUtf8 extends ConstantInfo {
public String value;

@Override
public void read(InputStream inputStream) {
int length = U2.read(inputStream);
byte[] bytes = new byte[length];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
try {
value = readUtf8(bytes);
} catch (UTFDataFormatException e) {
e.printStackTrace();
}
}

private String readUtf8(byte[] bytearr) throws UTFDataFormatException {
//copy from java.io.DataInputStream.readUTF()
}
}

ºÜ¼òµ¥£¬Ê×ÏȶÁÈ¡ÕâÒ»ÏîµÄ×Ö½ÚÊý×鳤¶È£¬½Ó×ŵ÷ÓÃreadUtf8(),½«×Ö½ÚÊý×éת»¯ÎªString×Ö·û´®¡£

ÔÙÀ´¿´¿´CONSTANT_ClassÕâÒ»ÏÕâÒ»Ïî´æ´¢µÄÊÇÀà»òÕ߽ӿڵķûºÅÒýÓãº

CONSTANT_Class_info {
u1 tag;
u2 name_index;
}

×¢ÒâÕâÀïµÄname_index²¢²»ÊÇÖ±½ÓµÄ×Ö·û´®£¬¶øÊÇÖ¸Ïò³£Á¿³ØÖÐcpInfoÊý×éµÄname_indexÏÇÒcpInfo[name_index]Ò»¶¨ÊÇCONSTANT_Utf8¸ñʽ¡£

public class ConstantClass extends ConstantInfo {
public int nameIndex;

@Override
public void read(InputStream inputStream) {
nameIndex = U2.read(inputStream);
}
}

³£Á¿³Ø½âÎöÍê±Ïºó£¬¾Í¿ÉÒÔ¹©ºóÃæµÄÊý¾ÝʹÓÃÁË£¬±È·½ËµClassFileÖеÄthis_classÖ¸ÏòµÄ¾ÍÊdz£Á¿³ØÖиñʽΪCONSTANT_ClassµÄijһÏî,ÄÇôÎÒÃǾͿÉÒÔ¶ÁÈ¡³öÀàÃû£º

int classIndex = U2.read(inputStream);
ConstantClass clazz = (ConstantClass) constantPool.cpInfo[classIndex];
ConstantUtf8 className = (ConstantUtf8) constantPool.cpInfo[clazz.nameIndex];
classFile.className = className.value;
System.out.print("classname:" + classFile.className + "\n");

×Ö½ÚÂëÖ¸Áî

½âÎö³£Á¿³ØÖ®ºó»¹ÐèÒª½Ó׎âÎöһЩÀàÐÅÏ¢£¬È縸Àà¡¢½Ó¿ÚÀà¡¢×ֶεȣ¬µ«ÊÇÏàÐÅ´ó¼Ò×îºÃÆæµÄ»¹ÊÇjavaÖ¸ÁîµÄ´æ´¢£¬´ó¼Ò¶¼ÖªµÀ£¬ÎÒÃÇÆ½Ê±Ð´µÄjava´úÂë»á±»±àÒë³Éjava×Ö½ÚÂ룬ÄÇôÕâЩ×Ö½ÚÂëµ½µ×´æ´¢ÔÚÄÄÄØ£¿±ð¼±£¬½²½âÖ¸Áî֮ǰ£¬ÎÒÃÇÏÈÀ´Á˽âÏÂClassFileÖеÄmethod_info£¬Æä¸ñʽÈçÏ£º

method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}

method_infoÀïÖ÷ÒªÊÇһЩ·½·¨ÐÅÏ¢£ºÈç·ÃÎʱêÖ¾¡¢·½·¨ÃûË÷Òý¡¢·½·¨ÃèÊö·ûË÷Òý¼°ÊôÐÔÊý×é¡£ÕâÀïҪǿµ÷µÄÊÇÊôÐÔÊý×飬ÒòΪ×Ö½ÚÂëÖ¸Áî¾Í´æ´¢ÔÚÕâ¸öÊôÐÔÊý×éÀï¡£ÊôÐÔÓкܶàÖÖ£¬±ÈÈç˵Òì³£±í¾ÍÊÇÒ»¸öÊôÐÔ£¬¶ø´æ´¢×Ö½ÚÂëÖ¸ÁîµÄÊôÐÔΪCODEÊôÐÔ£¬¿´ÕâÃû×ÖÒ²ÖªµÀÊÇÓÃÀ´´æ´¢´úÂëµÄÁË¡£ÊôÐÔµÄͨÓøñʽΪ£º

attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}

¸ù¾Ýattribute_name_index¿ÉÒÔ´Ó³£Á¿³ØÖÐÄõ½ÊôÐÔÃû£¬ÔÙ¸ù¾ÝÊôÐÔÃû¾Í¿ÉÒÔÅжÏÊôÐÔÖÖÀàÁË¡£

CodeÊôÐԵľßÌå¸ñʽΪ£º

Code_attribute {
u2 attribute_name_index; u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{
u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

ÆäÖÐcodeÊý×éÀï´æ´¢¾ÍÊÇ×Ö½ÚÂëÖ¸ÁÄÇôÈçºÎ½âÎöÄØ£¿Ã¿ÌõÖ¸ÁîÔÚcode[]Öж¼ÊÇÒ»¸ö×Ö½Ú£¬ÎÒÃÇÆ½Ê±javapÃüÁî·´±àÒë¿´µ½µÄÖ¸ÁîÆäʵÊÇÖú¼Ç·û£¬Ö»ÊÇ·½±ãÔĶÁ×Ö½ÚÂëʹÓõģ¬jvmÓÐÒ»ÕÅ×Ö½ÚÂëÓëÖú¼Ç·ûµÄ¶ÔÕÕ±í£¬¸ù¾Ý¶ÔÕÕ±í£¬¾Í¿ÉÒÔ½«Ö¸Áî·­ÒëΪ¿É¶ÁµÄÖú¼Ç·ûÁË¡£ÕâÀïÎÒÒ²ÊÇÔÚÍøÉÏËæ±ãÕÒÁËÒ»¸ö¶ÔÕÕ±í£¬±£´æµ½±¾µØtxtÎļþÖУ¬²¢ÔÚʹÓÃʱ½âÎö³ÉHashMap¡£´úÂëºÜ¼òµ¥£¬¾Í²»ÌùÁË£¬¿ÉÒԲο¼ÎÒ´úÂëÖÐInstructionTable.java¡£

½ÓÏÂÀ´ÎÒÃǾͿÉÒÔ½âÎö×Ö½ÚÂëÁË£º

for (int j = 0; j < methodInfo.attributesCount; j++) {
if (methodInfo.attributes[j] instanceof CodeAttribute) {
CodeAttribute codeAttribute = (CodeAttribute) methodInfo.attributes[j];
for (int m = 0; m < codeAttribute.codeLength; m++) {
short code = codeAttribute.code[m];
System.out.print(InstructionTable.getInstruction(code) + "\n");
}
}
}

ÔËÐÐ

Õû¸öÏîÄ¿ÖÕÓÚдÍêÁË£¬½ÓÏÂÀ´¾ÍÀ´¿´¿´Ð§¹ûÈçºÎ£¬Ëæ±ãÕÒÒ»¸öclassÎļþ½âÎöÔËÐУº

¹þ¹þ£¬ÊDz»ÊǺÜÔÞ£¡

   
1962 ´Îä¯ÀÀ       32
Ïà¹ØÎÄÕÂ

Java΢·þÎñÐÂÉú´úÖ®Nacos
ÉîÈëÀí½âJavaÖеÄÈÝÆ÷
JavaÈÝÆ÷Ïê½â
Java´úÂëÖÊÁ¿¼ì²é¹¤¾ß¼°Ê¹Óð¸Àý
Ïà¹ØÎĵµ

JavaÐÔÄÜÓÅ»¯
Spring¿ò¼Ü
SSM¿ò¼Ü¼òµ¥¼òÉÜ
´ÓÁ㿪ʼѧjava±à³Ì¾­µä
Ïà¹Ø¿Î³Ì

¸ßÐÔÄÜJava±à³ÌÓëϵͳÐÔÄÜÓÅ»¯
JavaEE¼Ü¹¹¡¢ Éè¼ÆÄ£Ê½¼°ÐÔÄܵ÷ÓÅ
Java±à³Ì»ù´¡µ½Ó¦Óÿª·¢
JAVAÐéÄâ»úÔ­ÀíÆÊÎö
×îл¼Æ»®
ǶÈëʽÈí¼þ¼Ü¹¹Éè¼Æ 12-11[±±¾©]
LLM´óÄ£ÐÍÓëÖÇÄÜÌ忪·¢ÊµÕ½ 12-18[±±¾©]
ǶÈëʽÈí¼þ²âÊÔ 12-25[±±¾©]
AIÔ­ÉúÓ¦ÓõÄ΢·þÎñ¼Ü¹¹ 1-9[±±¾©]
AI´óÄ£Ðͱàд¸ßÖÊÁ¿´úÂë 1-14[±±¾©]
ÐèÇó·ÖÎöÓë¹ÜÀí 1-22[±±¾©]

Java ÖеÄÖÐÎıàÂëÎÊÌâ
Java»ù´¡ÖªÊ¶µÄÈýÊ®¸ö¾­µäÎÊ´ð
Íæ×ª Java Web Ó¦Óÿª·¢
ʹÓÃSpring¸üºÃµØ´¦ÀíStruts
ÓÃEclipse¿ª·¢iPhone WebÓ¦ÓÃ
²å¼þϵͳ¿ò¼Ü·ÖÎö

Struts+Spring+Hibernate
»ùÓÚJ2EEµÄWeb 2.0Ó¦Óÿª·¢
J2EEÉè¼ÆÄ£Ê½ºÍÐÔÄܵ÷ÓÅ
Java EE 5ÆóÒµ¼¶¼Ü¹¹Éè¼Æ
Javaµ¥Ôª²âÊÔ·½·¨Óë¼¼Êõ
Java±à³Ì·½·¨Óë¼¼Êõ

Struts+Spring+Hibernate/EJB+ÐÔÄÜÓÅ»¯
»ªÏÄ»ù½ð ActiveMQ Ô­ÀíÓë¹ÜÀí
ijÃñº½¹«Ë¾ Java»ù´¡±à³Ìµ½Ó¦Óÿª·¢
ij·çµç¹«Ë¾ Java Ó¦Óÿª·¢Æ½Ì¨ÓëÇ¨ÒÆ
ÈÕÕÕ¸Û J2EEÓ¦Óÿª·¢¼¼Êõ¿ò¼ÜÓëʵ¼ù
ij¿ç¹ú¹«Ë¾ ¹¤×÷Á÷¹ÜÀíJBPM
¶«·½º½¿Õ¹«Ë¾ ¸ß¼¶J2EE¼°ÆäÇ°ÑØ¼¼Êõ