反编译那些事儿—枚举的反编译

Posted 编程老高

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反编译那些事儿—枚举的反编译相关的知识,希望对你有一定的参考价值。

说明:下面的反编译结果使用“ http://download.csdn.net/detail/wangshuxuncom/6841823”处的反编译工具反编译的。

一、不含有抽象的方法

源码如下:

import java.util.Arrays;
import java.util.List;

public enum Weather 

	Sunny(1, "晴天"), Rainy(2, "雨天"), Cloudy(3, "多云");
	private int value;
	private String label;

	private Weather(int value, String label) 
		this.value = value;
		this.label = label;
	

	public int getValue() 
		return value;
	

	public String getLabel() 
		return label;
	

	public static Weather parse(int value) 
		Weather result = Weather.Sunny;
		switch (value) 
		case 1:
			result = Weather.Sunny;
			break;
		case 2:
			result = Weather.Rainy;
			break;
		case 3:
			result = Weather.Cloudy;
			break;
		
		return result;
	

	public static List<Weather> getEnumValues() 
		return Arrays.asList(values());
	

	public static void main(String[] args) 
		System.out.println(Weather.Sunny.getValue() + ":" + Weather.Sunny.getLabel());
		Weather weather = Weather.Cloudy;
		System.out.println(weather.getValue() + ":" + weather.getLabel());
		List<Weather> list = getEnumValues();
		for (Weather sw : list) 
			System.out.println(sw.value + "--" + sw.label);
		
	

反编译生成的class文件后的代码如下:

/*import java.io.PrintStream;*/
import java.util.*;

public final class Weather extends Enum
	
	private Weather(/*String s, int i,*/ int value, String label)
		/*super(s, i);*/
		this.value = value;
		this.label = label;
	
	
	public int getValue()
		return value;
	
	
	public String getLabel()
		return label;
	
	
	public static Weather parse(int value)
		Weather result = Sunny;
		switch(value)
			case 1: /*// '\\001'*/
				result = Sunny;
				break;
			case 2: /*// '\\002'*/
				result = Rainy;
				break;
			case 3: /*// '\\003'*/
				result = Cloudy;
				break;
		
		return result;
	
	
	public static List getEnumValues()
		return Arrays.asList(values());
	
	
	public static void main(String args[])
		System.out.println((new StringBuilder(String.valueOf(Sunny.getValue()))).append(":").append(Sunny.getLabel()).toString());
		Weather weather = Cloudy;
		System.out.println((new StringBuilder(String.valueOf(weather.getValue()))).append(":").append(weather.getLabel()).toString());
		List list = getEnumValues();
		Weather sw;
		for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println((new StringBuilder(String.valueOf(sw.value))).append("--").append(sw.label).toString()))
			sw = (Weather)iterator.next();
	
	
	/*public static Weather[] values()
		Weather aweather[];
		int i;
		Weather aweather1[];
		System.arraycopy(aweather = ENUM$VALUES, 0, aweather1 = new Weather[i = aweather.length], 0, i);
		return aweather1;
	*/
	
	/*public static Weather valueOf(String s)
		return (Weather)Enum.valueOf(Weather, s);
	*/
	
	/*public static final Weather*/ Sunny;
	/*public static final Weather*/ Rainy;
	/*public static final Weather*/ Cloudy;
	private int value;
	private String label;
	/*private static final Weather ENUM$VALUES[];*/
	static 
		Sunny = new Weather(/*"Sunny", 0,*/ 1, "\\u6674\\u5929");
		Rainy = new Weather(/*"Rainy", 1,*/ 2, "\\u96E8\\u5929");
		Cloudy = new Weather(/*"Cloudy", 2,*/ 3, "\\u591A\\u4E91");
		/*ENUM$VALUES = (new Weather[] 
			Sunny, Rainy, Cloudy
		);*/
	

注意:所有/**/中间的东西都是多余的(/**/是人为添加的)

如何将反编译代码还原:

①、去掉被/**/掉的代码,去掉后代码如下:

import java.util.*;

public final class Weather extends Enum
    private Weather(int value, String label)
    	this.value = value;
    	this.label = label;
    

    public int getValue()
    	return value;
    

    public String getLabel()
    	return label;
    

    public static Weather parse(int value)
         Weather result = Sunny;
         switch(value)
         	case 1:
         		result = Sunny;
         			break;
         	case 2:
         		result = Rainy;
         		break;
         	case 3:
         		result = Cloudy;
         		break;
        
        return result;
    

    public static List getEnumValues()
    	return Arrays.asList(values());
    

    public static void main(String args[])
    	System.out.println((new StringBuilder(String.valueOf(Sunny.getValue()))).append(":").append(Sunny.getLabel()).toString());
        Weather weather = Cloudy;
        System.out.println((new StringBuilder(String.valueOf(weather.getValue()))).append(":").append(weather.getLabel()).toString());
        List list = getEnumValues();
        Weather sw;
        for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println((new StringBuilder(String.valueOf(sw.value))).append("--").append(sw.label).toString()))
        sw = (Weather)iterator.next();
	

    Sunny;
    Rainy;
    Cloudy;
    private int value;
    private String label;
    static 
    	Sunny = new Weather(1, "\\u6674\\u5929");
    	Rainy = new Weather(2, "\\u96E8\\u5929");
    	Cloudy = new Weather(3, "\\u591A\\u4E91");
    

②、在上一步的基础上对照非反编译中的java源码可以还原大概,呵呵呵,可能你会说“狗屁,我要是知道源码了,还反编译干什么”,呵呵呵,别急,如果你能把上面的这个弄明白了,你就会反编译没有源码参考的枚举类了。

③、呵呵呵,本来到此就可以了事了,可是还是禁不住提几个地方:注意反编译前java文件和反编译后生成的java文件在引类的区别;注意反编译class文件后的泛型没有了;从反编译的结果中可以得出这样的结论:实际上枚举类型就是以Java类来实现的,没有什么新的特点,只不过java编译器帮我们做了语法的解析和编译。

二、含有抽象的方法

源码如下:

import java.util.Arrays;
import java.util.List;

public enum Weather 
	
	Sunny(1, "晴天") 
		@Override
		public String test() 
			return "今天阳光明媚!!!\\n";
		
	,
	Rainy(2, "雨天") 
		@Override
		public String test() 
			return "出门别忘带把雨伞哦!!!\\n";
		
	,
	Cloudy(3, "多云") 
		@Override
		public String test() 
			return "别出去登高望远了,你看不远的,呵呵呵!!!\\n";
		
	;

	private int value;
	private String label;

	private Weather(int value, String label) 
		this.value = value;
		this.label = label;
	

	public int getValue() 
		return value;
	

	public String getLabel() 
		return label;
	

	public abstract String test();

	public static Weather parse(int value) 
		Weather result = Weather.Sunny;
		switch (value) 
		case 1:
			result = Weather.Sunny;
			break;
		case 2:
			result = Weather.Rainy;
			break;
		case 3:
			result = Weather.Cloudy;
			break;
		
		return result;
	

	public static List<Weather> getEnumValues() 
		return Arrays.asList(values());
	

	public static void main(String[] args) 
		System.out.println(Weather.Sunny.getValue() + ":" + Weather.Sunny.getLabel());
		Weather weather = Weather.Cloudy;
		System.out.println(weather.getValue() + ":" + weather.getLabel() + "\\n\\n");
		List<Weather> list = getEnumValues();
		for (Weather sw : list) 
			System.out.println(sw.value + "--" + sw.label + "--" + sw.test());
		
	

反编译生成的class文件后的代码如下:

import java.io.PrintStream;
import java.util.*;

public abstract class Weather extends Enum 

	private Weather(String s, int i, int value, String label) 
		super(s, i);
		this.value = value;
		this.label = label;
	

	public int getValue() 
		return value;
	

	public String getLabel() 
		return label;
	

	public abstract String test();

	public static Weather parse(int value) 
		Weather result = Sunny;
		switch (value) 
		case 1: // '\\001'
			result = Sunny;
			break;
		case 2: // '\\002'
			result = Rainy;
			break;
		case 3: // '\\003'
			result = Cloudy;
			break;
		
		return result;
	

	public static List getEnumValues() 
		return Arrays.asList(values());
	

	public static void main(String args[]) 
		System.out.println((new StringBuilder(String.valueOf(Sunny.getValue()))).append(":").append(Sunny.getLabel()).toString());
		Weather weather = Cloudy;
		System.out.println((new StringBuilder(String.valueOf(weather.getValue()))).append(":").append(weather.getLabel()).append("\\n\\n").toString());
		List list = getEnumValues();
		Weather sw;
		for (Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println((new StringBuilder(String.valueOf(sw.value))).append("--").append(sw.label).append("--").append(sw.test()).toString()))
			sw = (Weather) iterator.next();
	

	public static Weather[] values() 
		Weather aweather[];
		int i;
		Weather aweather1[];
		System.arraycopy(aweather = ENUM$VALUES, 0, aweather1 = new Weather[i = aweather.length], 0, i);
		return aweather1;
	

	public static Weather valueOf(String s) 
		return (Weather) Enum.valueOf(Weather, s);
	

	Weather(String s, int i, int j, String s1, Weather weather) 
		this(s, i, j, s1);
	

	public static final Weather Sunny;
	public static final Weather Rainy;
	public static final Weather Cloudy;
	private int value;
	private String label;
	private static final Weather ENUM$VALUES[];

	static 
		Sunny = new Weather("Sunny", 0, 1, "\\u6674\\u5929") 
			public String test() 
				return "\\u4ECA\\u5929\\u9633\\u5149\\u660E\\u5A9A\\uFF01\\uFF01\\uFF01\\n";
			
		;
		Rainy = new Weather("Rainy", 1, 2, "\\u96E8\\u5929") 
			public String test() 
				return "\\u51FA\\u95E8\\u522B\\u5FD8\\u5E26\\u628A\\u96E8\\u4F1E\\u54E6\\uFF01\\uFF01\\uFF01\\n";
			
		;
		Cloudy = new Weather("Cloudy", 2, 3, "\\u591A\\u4E91") 
			public String test() 
				return "\\u522B\\u51FA\\u53BB\\u767B\\u9AD8\\u671B\\u8FDC\\u4E86\\uFF0C\\u4F60\\u770B\\u4E0D\\u8FDC\\u7684\\uFF0C\\u5475\\u5475\\u5475\\uFF01\\uFF01\\uFF01\\n";
			
		;
		ENUM$VALUES = (new Weather[]  Sunny, Rainy, Cloudy );
	

总结:对比源代码和编译代码,找出他们的区别并不难,做到这一点就可以反编译含有抽象方法的枚举class文件,呵呵呵呵,将“不含抽象方法”的class反编译文件和“含有抽象方法”的class反编译文件,你应该还有一个很大的收获,呵呵呵,看着:

“不含抽象方法”的class反编译文件:public final class Weather extends Enum

“含有抽象方法”的class反编译文件:public abstractclass Weather extends Enum

与50位技术专家面对面 20年技术见证,附赠技术全景图

以上是关于反编译那些事儿—枚举的反编译的主要内容,如果未能解决你的问题,请参考以下文章

Java代码的编译与反编译那些事儿

令人惊叹的反编译器!漫谈几种[反编译对抗技术]

应用的反编译

MyEclipse6.5的反编译插件的安装

Eclipse中的反编译(Jad)

c语言的反编译问题