import java.io.*; public class ClassAnalyzer { public static StringBuffer sb = new StringBuffer(); public static byte[] analyzeConstant_tag; public static String[] analyzeConstant_utf8; public static DataOutputStream dataout; public static void main(String[] args) { DataInputStream input = null; try { FileOutputStream out = new FileOutputStream( "d:\\home\\1.txt"); BufferedOutputStream buffout = new BufferedOutputStream(out); dataout = new DataOutputStream(buffout); input = new DataInputStream( new BufferedInputStream( new FileInputStream( "D:\\Workspaces\\MyEclipse 9.2\\test\\bin\\TestClass.class"))); // 获取文件大小 FileSize(new DataInputStream( new BufferedInputStream( new FileInputStream( "D:\\Workspaces\\MyEclipse 9.2\\test\\bin\\TestClass.class")))); // 解析数据 analyze(input); } catch (Exception e) { e.printStackTrace(); System.out.println("解析失败!"); } finally { try { input.close(); dataout.close(); } catch (Exception e) { } } } public static void FileSize(DataInputStream input) throws IOException { int length = 0; // 长度,字节,B double kblength = 0.0D; // 长度,千字节,KB while (input.read() != -1) ++length; kblength = length / 1024.0D; System.out.println("文件大小(字节):" + length + "\n文件大小(KB):" + kblength); input.close(); } public static void analyze(DataInputStream input) throws IOException { // 读取幻数 int magic = u4(input); if (magic == 0xCAFEBABE) // -889275714 System.out.println("magic number = 0xCAFEBABE -----标准class文件"); else { throw new RuntimeException("无效的幻数!"); } // 读取副、主版本号 int minor_ver = u2(input); int major_ver = u2(input); System.out.println("Version = " + major_ver + "." + minor_ver); add(" 常规信息 "); add("Minor version: " + minor_ver); add("Major version: " + major_ver); // 读取常量池表中表项的个数 short const_pool_count = u2(input); System.out.println("constant pool size = " + const_pool_count); add("Constant pool count: " + const_pool_count); // 读取每个常量 analyzeConstant_tag = new byte[const_pool_count]; // 存储常量数据类型 analyzeConstant_tag[0] = 0; // 系统保留,class中不存在 for (int i = 1; i < const_pool_count; ++i) analyzeConstant(input, i); // 分析常数 jiexitmp(); // 解析tmp文件 // 读取Class的声明中使用的修饰符掩码并解析 short access_flags = u2(input); System.out.print("access_flags = " + access_flags); String access_flags_16 = "0x" + Integer.toHexString(access_flags); int[] access = { 0x0001, 0x0010, 0x0020, 0x0200, 0x0400 }; String[] access_str = { "public", "final", "", "interface", "abstract" }; // NO.2--super String access_tmp = ""; for (int i = 0; i < access.length; i++) { if ((access_flags & access[i]) == access[i]) { if (i == 0) access_tmp += access_str[i]; else if (i != 2) access_tmp += " " + access_str[i]; } } System.out.println(" [" + access_tmp + " ]"); add("Access flags: " + access_flags_16 + " [" + access_tmp + " ]"); // 读取类或者接口的全限定名称 short this_class_index = u2(input); short super_class_index = u2(input); System.out.println("This class = " + this_class_index); System.out.println("Super class = " + super_class_index); add("This class: " + this_class_index); add("Super class: " + super_class_index); // read interfaces count: short interfaces_count = u2(input); System.out.println("超接口个数 = " + interfaces_count); add("Interfaces count: " + interfaces_count); // read each interface: for (int i = 1; i <= interfaces_count; i++) { short interface_index = u2(input); System.out.println("No. " + i + " interface index = " + interface_index); } } public static byte u1(DataInputStream input) throws IOException { return input.readByte(); } public static Short u2(DataInputStream input) throws IOException { return input.readShort(); } public static int u4(DataInputStream input) throws IOException { return input.readInt(); } public static long u8(DataInputStream input) throws IOException { return input.readLong(); } public static void add(String str) throws IOException { sb.append(str + "\n"); } public static void analyzeConstant(DataInputStream input, int index) throws IOException { // 用于读: byte n8; short n16; int n32; long n64; float f; double d; byte[] buffer; byte tag = input.readByte(); // 读取数据类型标签 analyzeConstant_tag[index] = tag; // 存储常量数据类型 System.out.println("\n常量索引 = " + index + ", 数据类型标签 = " + (int) tag); switch (tag) { case 1: // utf-8 string System.out.println(" 常量类型 = Utf8 //Utf8存储格式"); // Utf8存储格式 n16 = u2(input); System.out.println(" length = " + n16); dataout.writeShort(n16); buffer = new byte[n16]; input.readFully(buffer); // 数组读满才返回 System.out.println(" value = " + new String(buffer)); dataout.writeUTF(new String(buffer)); break; case 3: // integer System.out.println(" 常量类型 = Integer //Integer存储格式"); // Integer存储格式 n32 = u4(input); System.out.println(" value = " + n32); dataout.writeInt(n32); break; case 4: // float System.out.println(" 常量类型 = Float //Float存储格式"); // Float存储格式 f = u4(input);// input.readFloat(); System.out.println(" value = " + f); dataout.writeFloat(f); break; case 5: // long System.out.println(" 常量类型 = Long //Long存储格式"); // Long存储格式 n64 = u8(input); System.out.println(" value = " + n64); dataout.writeLong(n64); break; case 6: // double System.out.println(" 常量类型 = Double //Double存储格式"); // Double存储格式 d = u8(input); System.out.println(" value = " + d); dataout.writeDouble(d); break; case 7: // class or interface reference System.out.println(" 常量类型 = Class //类索引"); // 类索引 n16 = u2(input); System.out.println(" index = " + n16 + " (在哪里可以找到类名)"); dataout.writeShort(n16); break; case 8: // string System.out.println(" 常量类型 = String //字符串索引"); // 字符串索引 n16 = u2(input); System.out.println(" index = " + n16); dataout.writeShort(n16); break; case 9: // field reference System.out.println(" 常量类型 = Fieldref //领域参数"); // 领域参数 n16 = u2(input); System.out.println("class index = " + n16 + " (在哪里可以找到类名)"); dataout.writeShort(n16); n16 = u2(input); System.out.println("nameAndType = " + n16 + " (在哪里可以找到的名称和类型)"); dataout.writeShort(n16); break; case 10: // method reference System.out.println(" 常量类型 = Methodref //方法参考"); // 方法参考 n16 = u2(input); System.out.println("class index = " + n16 + " (在哪里可以找到类)"); dataout.writeShort(n16); n16 = u2(input); System.out.println("nameAndType = " + n16 + " (在哪里可以找到名称和类型)"); dataout.writeShort(n16); break; case 11: // interface method reference System.out.println(" 常量类型 = InterfaceMethodref //接口方法参考值"); // 接口方法参考值 n16 = u2(input); System.out.println("class index = " + n16 + " (在哪里可以找到接口)"); dataout.writeShort(n16); n16 = u2(input); System.out.println("nameAndType = " + n16 + " (在哪里可以找到名称和类型)"); dataout.writeShort(n16); break; case 12: // name and type reference System.out.println(" 常量类型 = NameAndType //名称和类型"); // 名称和类型 n16 = u2(input); System.out.println(" name index = " + n16 + " (在哪里可以找到这个名字)"); dataout.writeShort(n16); n16 = u2(input); System.out.println(" descripter = " + n16 + " (在哪里可以找到描述符)"); dataout.writeShort(n16); break; default: throw new RuntimeException("Invalid constant pool flag: " + tag); } // end switch } public static void jiexitmp() { DataInputStream input = null; try { input = new DataInputStream( new BufferedInputStream( new FileInputStream( "C:\\Documents and Settings\\Administrator\\桌面\\解析class文件\\ReadClass.tmp"))); /********** analyzeConstant_tag[]存储常量池表中常量数据类型(共11种) **********/ int[] tagSpecies = new int[11]; // 存储常量池表中常量各种数据类型的计数 int const_pool_count = analyzeConstant_tag.length; // 读取常量池表中表项的个数 for (int i = 0; i < const_pool_count; i++) // 对数据类型的计数数组进行赋值 { System.out.println(analyzeConstant_tag[i]); // 按顺序输出各种数据的类型 switch (analyzeConstant_tag[i]) { case 1: ++tagSpecies[0]; break; case 3: ++tagSpecies[1]; break; case 4: ++tagSpecies[2]; break; case 5: ++tagSpecies[3]; break; case 6: ++tagSpecies[4]; break; case 7: ++tagSpecies[5]; break; case 8: ++tagSpecies[6]; break; case 9: ++tagSpecies[7]; break; case 10: ++tagSpecies[8]; break; case 11: ++tagSpecies[9]; break; case 12: ++tagSpecies[10]; break; } } for (int i = 0; i < tagSpecies.length; i++) System.out.println("数量" + tagSpecies[i]);/* * analyzeConstant_utf8 * = new String[ * analyzeConstant_utf8_num * ]; int j = 0; for(int * i * =0;i<const_pool_count * ;i++) * if(analyzeConstant_tag * [i]==1) * analyzeConstant_utf8 * [j++] = "r"; for(int * i * =0;i<analyzeConstant_utf8 * .length;i++) * System.out * .println("NO."+i+" "+ * analyzeConstant_utf8 * [i]); */ } catch (Exception e) { System.out.println("解析失败!"); } finally { try { input.close(); } catch (Exception e) { } } } } // End /***** * byte u1 Short u2 int u4 ClassFile表结构 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]; } * * 1//Utf8存储格式 dataout.writeShort(n16); //length dataout.writeUTF(new * String(buffer)); //字符串 3//Integer存储格式 dataout.writeInt(n32); 4//Float存储格式 * dataout.writeFloat(f); 5//Long存储格式 dataout.writeLong(n64); 6//Double存储格式 * dataout.writeDouble(d); 7//类索引 dataout.writeShort(n16); 8//字符串索引 * dataout.writeShort(n16); 9//领域参数 dataout.writeShort(n16); //类名 * dataout.writeShort(n16); //名称和类型 10//方法参考 dataout.writeShort(n16); //类名 * dataout.writeShort(n16); //名称和类型 11//接口方法参考值 dataout.writeShort(n16); //接口 * dataout.writeShort(n16); //名称和类型 12//名称和类型 dataout.writeShort(n16); //名字索引 * dataout.writeShort(n16); //描述符索引 *****/
转载 http://www.360doc.com/content/10/0913/04/3317721_53227485.shtml
相关推荐
根据接口类名称和jar文件读取class文件 可以改造成根据package名读取class文件等等。。。 扩展性很强一读既懂
class文件查看器,可以查看class文件,转译出代码.方便大家使用.(java工具类)简单的工具没这么多说明,说这些只是为了凑字数啦啦啦啦
Java反编译是一种技术,它允许开发者查看已编译的.class文件中的源代码,即使原始的.java文件不再可用。这通常在需要理解第三方库的工作原理、逆向工程或调试二进制代码时变得非常有用。在Java中,由于类文件是经过...
在IT行业中,开发人员经常需要处理已编译的`.class`文件,特别是在没有源代码的情况下。`MyEclipse`是一款强大的Java集成开发环境(IDE),它提供了丰富的功能,包括对`.class`文件的查看和分析。本文将详细介绍如何...
在Python2中,由于其对字节操作的支持,可以直接读取Class文件的字节流,逐个解析字节码指令。每个指令都对应着JVM的一次操作,如加载常量、做算术运算、调用方法等。Python程序可以模拟JVM的栈操作,按照指令的顺序...
JVM通过读取Class文件中的指令集来执行Java程序,这些指令集被设计成与平台无关的中间代码,使得Java程序可以在任何支持Java的平台上运行而无需重新编译。 总之,Class文件格式是Java生态系统中的关键组成部分,它...
Class文件查看软件.rarClass文件查看软件.rarClass文件查看软件.rar
Java Class文件是Java程序经过编译后的二进制表示形式,它是Java虚拟机(JVM)执行的基础。本文将深入探讨Java类文件的结构、编译过程以及如何使用提供的工具进行查看。 一、Java类文件结构 Java源代码(.java文件...
Java虚拟机通过读取Class文件来运行程序。 二、Class编译工具:javac 在Windows环境下,Java Class文件的编译主要依赖于Java Development Kit(JDK)中的javac命令行工具。javac是一个源码编译器,它将.java源代码...
- 首先,反编译器读取Class文件的二进制数据,解析其结构。 - 然后,根据字节码指令解析出方法体,转换为高级语言的逻辑结构。 - 最后,生成类似于原始Java源代码的文本输出。 4. **使用场景**: - **代码恢复*...
1. 读取Class文件:反编译器首先读取Class文件的二进制内容。 2. 解析字节码:理解Class文件的结构,包括常量池、字段、方法、接口等信息。 3. 反编译指令:将字节码指令转换为高级语言表达式。 4. 构建源代码:根据...
类加载器不仅负责从磁盘、网络或其他来源读取Class文件,还参与了类的动态加载和卸载过程,这在进行JVM调优和复杂应用设计时非常重要。 总的来说,理解和掌握Class文件结构、JVM的工作原理以及类加载器的功能对于...
### JVM加载Class文件详解 #### 一、Java与JVM中的Class文件加载机制概述 Java作为一种动态性极强的解释型编程语言,在程序运行时,Java虚拟机(JVM)负责将编译生成的`.class`文件加载到内存中进行执行。在Java...
本文将深入探讨jar包的读取和class文件的理解,以及如何使用工具进行操作。 一、jar包的结构与读取 1. jar包结构:jar文件本质上是一个基于ZIP格式的文件,包含了一个或多个.class文件,以及相关的资源文件(如图片...
总的来说,ClassFinal作为一款Java class文件安全加密工具,为开发者提供了一种简单、高效的代码保护方案,尤其适合于那些重视代码安全但又不想改动大量代码的企业级项目。其兼容性和易用性使其在Java开发领域具有...
在`loadClassFromPath`方法中,我们读取指定路径的class文件,然后调用`defineClass`方法将字节码转换为类。 总结来说,Java类动态加载是一种强大的技术,可以用于实现插件系统、热部署等功能。通过自定义...
对于更复杂的分析,可以编写代码解析Class文件,如描述中的"classinfo"项目,这通常涉及对二进制流的读取和解析,理解每个字段的含义,并构建出对应的类结构。 总之,Java Class文件是JVM运行的基础,包含了程序的...
标题中的“提取源文件和class文件的Eclipse插件”是指一种特定的Eclipse开发环境扩展,它的主要功能是方便开发者快速地从Eclipse的工作区中导出项目的源代码(.java文件)和编译后的字节码文件(.class文件)。...
在Java应用开发中,源代码的保护至关重要,因为Java的字节码(class文件)是可被反编译的,这可能导致源代码泄露、恶意篡改等安全风险。ClassFinal通过特定的加密算法和混淆技术,对Java类文件进行处理,使得未经...
在Java编程语言中,按顺序读取文件是基础且重要的操作。这通常涉及到使用I/O流(Input/Output Stream)来处理文件数据。本篇文章将深入探讨如何在Java中实现按顺序读取文件,以及涉及的相关知识点。 首先,Java提供...