`
yubinglin
  • 浏览: 689 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

class 字节码研究,针对动态代理源码深入研究

    博客分类:
  • JVM
 
阅读更多
package proxy;

import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;

public class ProxyGenerator {
/**
* @description 常量池
* @author yubinglin
* @date 2013-3-4
*/
private static class ConstantPool {
private static abstract class Entry {

public abstract void write(DataOutputStream dataoutputstream) throws IOException;

private Entry() {
}

}

/**
* 符号引用
*
* constant_fieldref_info 9 字段的符号引用 constant_method_info 10 类中方法的符号引用
* constant_interfaceMethodref_info 11 接口中的方法符号引用
* constant_nameandtype_info 12 字段或方法部分符号引用
*
* @author yubinglin
*
*/
private static class IndirectEntry extends Entry {

public void write(DataOutputStream dataoutputstream) throws IOException {
dataoutputstream.writeByte(tag);// 标志位
dataoutputstream.writeShort(index0);
if (tag == 9 || tag == 10 || tag == 11 || tag == 12)
dataoutputstream.writeShort(index1);
}

public int hashCode() {
return tag + index0 + index1;
}

public boolean equals(Object obj) {
if (obj instanceof IndirectEntry) {
IndirectEntry indirectentry = (IndirectEntry) obj;
if (tag == indirectentry.tag && index0 == indirectentry.index0 && index1 == indirectentry.index1)
return true;
}
return false;
}

private int tag;
private short index0;
private short index1;

public IndirectEntry(int i, short word0) {
tag = i;
index0 = word0;
index1 = 0;
}

public IndirectEntry(int i, short word0, short word1) {
tag = i;
index0 = word0;
index1 = word1;
}
}

/**
* constant_utf8_info 1 utf-8 编码的字符串 constant_integer_info 3 整形字面量
* constant_float_info 4 浮点型字面量 constant_long_info 5 长整形字面量
* constant_double_info 6 双精度浮点型字面量
*
* @author yubinglin 下面几种是常量池中的字面量,注意:常量池中一共11种表结构,两种类型字面量和符号引用
*/
private static class ValueEntry extends Entry {

public void write(DataOutputStream dataoutputstream) throws IOException {
if (value instanceof String) {
dataoutputstream.writeByte(1);
dataoutputstream.writeUTF((String) value);
} else if (value instanceof Integer) {
dataoutputstream.writeByte(3);
dataoutputstream.writeInt(((Integer) value).intValue());
} else if (value instanceof Float) {
dataoutputstream.writeByte(4);
dataoutputstream.writeFloat(((Float) value).floatValue());
} else if (value instanceof Long) {
dataoutputstream.writeByte(5);
dataoutputstream.writeLong(((Long) value).longValue());
} else if (value instanceof Double) {
dataoutputstream.writeDouble(6D);
dataoutputstream.writeDouble(((Double) value).doubleValue());
} else {
throw new InternalError((new StringBuilder()).append("bogus value entry: ").append(value).toString());
}
}

private Object value;

public ValueEntry(Object obj) {
value = obj;
}
}

/**
* 获取utf-8字符串的索引
*
* @param s
* @return
*/
public short getUtf8(String s) {
if (s == null)
throw new NullPointerException();
else
return getValue(s);
}

public short getInteger(int i) {
return getValue(new Integer(i));
}

public short getFloat(float f) {
return getValue(new Float(f));
}

public short getClass(String s) {
short word0 = getUtf8(s);
return getIndirect(new IndirectEntry(7, word0));
}

public short getString(String s) {
short word0 = getUtf8(s);
return getIndirect(new IndirectEntry(8, word0));
}

public short getFieldRef(String s, String s1, String s2) {
short word0 = getClass(s);
short word1 = getNameAndType(s1, s2);
return getIndirect(new IndirectEntry(9, word0, word1));
}

public short getMethodRef(String s, String s1, String s2) {
short word0 = getClass(s);
short word1 = getNameAndType(s1, s2);
return getIndirect(new IndirectEntry(10, word0, word1));
}

public short getInterfaceMethodRef(String s, String s1, String s2) {
short word0 = getClass(s);
short word1 = getNameAndType(s1, s2);
return getIndirect(new IndirectEntry(11, word0, word1));
}

public short getNameAndType(String s, String s1) {
short word0 = getUtf8(s);
short word1 = getUtf8(s1);
return getIndirect(new IndirectEntry(12, word0, word1));
}

public void setReadOnly() {
readOnly = true;
}

/**
* 常量池的信息写入字节流
*
* @param outputstream
* @throws IOException
*/
public void write(OutputStream outputstream) throws IOException {
DataOutputStream dataoutputstream = new DataOutputStream(outputstream);
dataoutputstream.writeShort(pool.size() + 1);
Entry entry;
for (Iterator iterator = pool.iterator(); iterator.hasNext(); entry.write(dataoutputstream))
entry = (Entry) iterator.next();

}

/**
* 添加常量,并返回索引
*
* @param entry
* @return
*/
private short addEntry(Entry entry) {
pool.add(entry);
if (pool.size() >= 65535)
throw new IllegalArgumentException("constant pool size limit exceeded");
else
return (short) pool.size();
}

/**
* 根据实体返回索引
*
* @param obj
* @return
*/
private short getValue(Object obj) {
Short short1 = (Short) map.get(obj);
if (short1 != null)
return short1.shortValue();
if (readOnly) {
throw new InternalError((new StringBuilder()).append("late constant pool addition: ").append(obj).toString());
} else {
short word0 = addEntry(new ValueEntry(obj));
map.put(obj, new Short(word0));
return word0;
}
}

/**
* 根据实体返回索引
*
* @param indirectentry
* @return
*/
private short getIndirect(IndirectEntry indirectentry) {
Short short1 = (Short) map.get(indirectentry);
if (short1 != null)
return short1.shortValue();
if (readOnly) {
throw new InternalError("late constant pool addition");
} else {
short word0 = addEntry(indirectentry);
map.put(indirectentry, new Short(word0));
return word0;
}
}

private List pool;
private Map map;
private boolean readOnly;

private ConstantPool() {
pool = new ArrayList(32);// 常量池
map = new HashMap(16);
readOnly = false;
}

}

/**
* code属性里面的异常表
*
* @author yubinglin
*
*/
private static class ExceptionTableEntry {

public short startPc;// 开始行
public short endPc;// 结束行
public short handlerPc;// 执行的句柄
public short catchType;// 跳转索引

public ExceptionTableEntry(short word0, short word1, short word2, short word3) {
startPc = word0;
endPc = word1;
handlerPc = word2;
catchType = word3;
}
}

/**
* 字段表
*
* @author yubinglin
* @date 2014-3-5
*/
private class FieldInfo {

public void write(DataOutputStream dataoutputstream) throws IOException {
dataoutputstream.writeShort(accessFlags);
dataoutputstream.writeShort(cp.getUtf8(name));
dataoutputstream.writeShort(cp.getUtf8(descriptor));
dataoutputstream.writeShort(0);
}

public int accessFlags;// 访问标志,public private static
public String name;// 名称
public String descriptor;// 字段类型
final ProxyGenerator this$0;

/**
* 名称、类型、可见性
*
* @param s
* @param s1
* @param i
*/
public FieldInfo(String s, String s1, int i) {
super();
this$0 = ProxyGenerator.this;
name = s;
descriptor = s1;
accessFlags = i;
cp.getUtf8(s);
cp.getUtf8(s1);
}
}

/**
* 方法表集合,包含属性表
*
* @author yubinglin
*
*/
private class MethodInfo {

public void write(DataOutputStream dataoutputstream) throws IOException {
dataoutputstream.writeShort(accessFlags);// 访问标志
dataoutputstream.writeShort(cp.getUtf8(name));// 名称索引
dataoutputstream.writeShort(cp.getUtf8(descriptor));// 描述索引
dataoutputstream.writeShort(2);// 属性表的数量,为什么就2个呢,就两个方法

dataoutputstream.writeShort(cp.getUtf8("Code"));// 属性表索引
dataoutputstream.writeInt(12 + code.size() + 8 * exceptionTable.size());// 属性值
// 的长度
// 12:maxStack+maxLocals+codelength+attrouslength
dataoutputstream.writeShort(maxStack);
dataoutputstream.writeShort(maxLocals);
dataoutputstream.writeInt(code.size());
code.writeTo(dataoutputstream);
dataoutputstream.writeShort(exceptionTable.size());

/**
* 异常表
*/
ExceptionTableEntry exceptiontableentry;
for (Iterator iterator = exceptionTable.iterator(); iterator.hasNext(); dataoutputstream.writeShort(exceptiontableentry.catchType)) {
exceptiontableentry = (ExceptionTableEntry) iterator.next();
dataoutputstream.writeShort(exceptiontableentry.startPc);
dataoutputstream.writeShort(exceptiontableentry.endPc);
dataoutputstream.writeShort(exceptiontableentry.handlerPc);
}

dataoutputstream.writeShort(0);// 最后属性的长度为0
/**
* 异常
*/
dataoutputstream.writeShort(cp.getUtf8("Exceptions"));
dataoutputstream.writeInt(2 + 2 * declaredExceptions.length);
dataoutputstream.writeShort(declaredExceptions.length);
for (int i = 0; i < declaredExceptions.length; i++)
dataoutputstream.writeShort(declaredExceptions[i]);

}

public int accessFlags;// 访问标志
public String name;// 方法名称
public String descriptor;// 可见性
public short maxStack;// 栈的索引
public short maxLocals;// 局部变量的索引,注意局部变量以slot为单位进行存储
public ByteArrayOutputStream code;// 指令码
public List exceptionTable;// 异常表集合
public short declaredExceptions[];
final ProxyGenerator this$0;

public MethodInfo(String s, String s1, int i) {
this$0 = ProxyGenerator.this;

code = new ByteArrayOutputStream();
exceptionTable = new ArrayList();
name = s;
descriptor = s1;
accessFlags = i;
cp.getUtf8(s);
cp.getUtf8(s1);
cp.getUtf8("Code");// 属性名称固定为Code
cp.getUtf8("Exceptions");
}
}

/**
* 基本类型
*
* @author yubinglin
*
*/
private static class PrimitiveTypeInfo {

private static void add(Class class1, Class class2) {
table.put(class1, new PrimitiveTypeInfo(class1, class2));
}

public static PrimitiveTypeInfo get(Class class1) {
return (PrimitiveTypeInfo) table.get(class1);
}

public String baseTypeString;
public String wrapperClassName;
public String wrapperValueOfDesc;
public String unwrapMethodName;
public String unwrapMethodDesc;
private static Map table = new HashMap();
static final boolean $assertionsDisabled = !ProxyGenerator.class.desiredAssertionStatus();

static {
add(Byte.TYPE, Byte.class);
add(Character.TYPE, Character.class);
add(Double.TYPE, Double.class);
add(Float.TYPE, Float.class);
add(Integer.TYPE, Integer.class);
add(Long.TYPE, Long.class);
add(Short.TYPE, Short.class);
add(Boolean.TYPE, Boolean.class);
}

private PrimitiveTypeInfo(Class class1, Class class2) {
if (!$assertionsDisabled && !class1.isPrimitive()) {
throw new AssertionError();
} else {
baseTypeString = Array.newInstance(class1, 0).getClass().getName().substring(1);// 获取基本类型
// 例如:Ljava.lang.String;
// 包装类的全限定名称
wrapperClassName = ProxyGenerator.dotToSlash(class2.getName());// 全限定名称:进行替换
// .替换成/
// java
// 包装类
// int的包装类Integer
// 方法描述符 例如 public String get(String date)
// (Ljava.lang.String)Ljava/lang/String
wrapperValueOfDesc = (new StringBuilder()).append("(").append(baseTypeString).append(")L").append(wrapperClassName).append(";").toString();

unwrapMethodName = (new StringBuilder()).append(class1.getName()).append("Value").toString();
unwrapMethodDesc = (new StringBuilder()).append("()").append(baseTypeString).toString();
return;
}
}
}

private class ProxyMethod {

private MethodInfo generateMethod() throws IOException {
String s = ProxyGenerator.getMethodDescriptor(parameterTypes, returnType);
MethodInfo methodinfo = new MethodInfo(methodName, s, 17);
int ai[] = new int[parameterTypes.length];
int i = 1;
for (int j = 0; j < ai.length; j++) {
ai[j] = i;
i += ProxyGenerator.getWordsPerType(parameterTypes[j]);
}

int k = i;
short word1 = 0;
DataOutputStream dataoutputstream = new DataOutputStream(methodinfo.code);
code_aload(0, dataoutputstream);
dataoutputstream.writeByte(180);
dataoutputstream.writeShort(cp.getFieldRef("java/lang/reflect/Proxy", "h", "Ljava/lang/reflect/InvocationHandler;"));
code_aload(0, dataoutputstream);
dataoutputstream.writeByte(178);
dataoutputstream.writeShort(cp.getFieldRef(ProxyGenerator.dotToSlash(className), methodFieldName, "Ljava/lang/reflect/Method;"));
if (parameterTypes.length > 0) {
code_ipush(parameterTypes.length, dataoutputstream);
dataoutputstream.writeByte(189);
dataoutputstream.writeShort(cp.getClass("java/lang/Object"));
for (int l = 0; l < parameterTypes.length; l++) {
dataoutputstream.writeByte(89);
code_ipush(l, dataoutputstream);
codeWrapArgument(parameterTypes[l], ai[l], dataoutputstream);
dataoutputstream.writeByte(83);
}

} else {
dataoutputstream.writeByte(1);
}
dataoutputstream.writeByte(185);
dataoutputstream.writeShort(cp.getInterfaceMethodRef("java/lang/reflect/InvocationHandler", "invoke",
"(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"));
dataoutputstream.writeByte(4);
dataoutputstream.writeByte(0);
if (returnType == Void.TYPE) {
dataoutputstream.writeByte(87);
dataoutputstream.writeByte(177);
} else {
codeUnwrapReturnValue(returnType, dataoutputstream);
}
short word0;
short word2 = word0 = (short) methodinfo.code.size();
List list = ProxyGenerator.computeUniqueCatchList(exceptionTypes);
if (list.size() > 0) {
Class class1;
for (Iterator iterator = list.iterator(); iterator.hasNext(); methodinfo.exceptionTable.add(new ExceptionTableEntry(word1, word2, word0, cp
.getClass(ProxyGenerator.dotToSlash(class1.getName())))))
class1 = (Class) iterator.next();

dataoutputstream.writeByte(191);
word0 = (short) methodinfo.code.size();
methodinfo.exceptionTable.add(new ExceptionTableEntry(word1, word2, word0, cp.getClass("java/lang/Throwable")));
code_astore(k, dataoutputstream);
dataoutputstream.writeByte(187);
dataoutputstream.writeShort(cp.getClass("java/lang/reflect/UndeclaredThrowableException"));
dataoutputstream.writeByte(89);
code_aload(k, dataoutputstream);
dataoutputstream.writeByte(183);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/reflect/UndeclaredThrowableException", "<init>", "(Ljava/lang/Throwable;)V"));
dataoutputstream.writeByte(191);
}
if (methodinfo.code.size() > 65535)
throw new IllegalArgumentException("code size limit exceeded");
methodinfo.maxStack = 10;
methodinfo.maxLocals = (short) (k + 1);
methodinfo.declaredExceptions = new short[exceptionTypes.length];
for (int i1 = 0; i1 < exceptionTypes.length; i1++)
methodinfo.declaredExceptions[i1] = cp.getClass(ProxyGenerator.dotToSlash(exceptionTypes[i1].getName()));

return methodinfo;
}

private void codeWrapArgument(Class class1, int i, DataOutputStream dataoutputstream) throws IOException {
if (class1.isPrimitive()) {
PrimitiveTypeInfo primitivetypeinfo = PrimitiveTypeInfo.get(class1);
if (class1 == Integer.TYPE || class1 == Boolean.TYPE || class1 == Byte.TYPE || class1 == Character.TYPE || class1 == Short.TYPE)
code_iload(i, dataoutputstream);
else if (class1 == Long.TYPE)
code_lload(i, dataoutputstream);
else if (class1 == Float.TYPE)
code_fload(i, dataoutputstream);
else if (class1 == Double.TYPE)
code_dload(i, dataoutputstream);
else
throw new AssertionError();
dataoutputstream.writeByte(184);
dataoutputstream.writeShort(cp.getMethodRef(primitivetypeinfo.wrapperClassName, "valueOf", primitivetypeinfo.wrapperValueOfDesc));
} else {
code_aload(i, dataoutputstream);
}
}

private void codeUnwrapReturnValue(Class class1, DataOutputStream dataoutputstream) throws IOException {
if (class1.isPrimitive()) {
PrimitiveTypeInfo primitivetypeinfo = PrimitiveTypeInfo.get(class1);
dataoutputstream.writeByte(192);
dataoutputstream.writeShort(cp.getClass(primitivetypeinfo.wrapperClassName));
dataoutputstream.writeByte(182);
dataoutputstream.writeShort(cp.getMethodRef(primitivetypeinfo.wrapperClassName, primitivetypeinfo.unwrapMethodName,
primitivetypeinfo.unwrapMethodDesc));
if (class1 == Integer.TYPE || class1 == Boolean.TYPE || class1 == Byte.TYPE || class1 == Character.TYPE || class1 == Short.TYPE)
dataoutputstream.writeByte(172);
else if (class1 == Long.TYPE)
dataoutputstream.writeByte(173);
else if (class1 == Float.TYPE)
dataoutputstream.writeByte(174);
else if (class1 == Double.TYPE)
dataoutputstream.writeByte(175);
else
throw new AssertionError();
} else {
dataoutputstream.writeByte(192);
dataoutputstream.writeShort(cp.getClass(ProxyGenerator.dotToSlash(class1.getName())));
dataoutputstream.writeByte(176);
}
}

private void codeFieldInitialization(DataOutputStream dataoutputstream) throws IOException {
codeClassForName(fromClass, dataoutputstream);
code_ldc(cp.getString(methodName), dataoutputstream);
code_ipush(parameterTypes.length, dataoutputstream);
dataoutputstream.writeByte(189);
dataoutputstream.writeShort(cp.getClass("java/lang/Class"));
for (int i = 0; i < parameterTypes.length; i++) {
dataoutputstream.writeByte(89);
code_ipush(i, dataoutputstream);
if (parameterTypes[i].isPrimitive()) {
PrimitiveTypeInfo primitivetypeinfo = PrimitiveTypeInfo.get(parameterTypes[i]);
dataoutputstream.writeByte(178);
dataoutputstream.writeShort(cp.getFieldRef(primitivetypeinfo.wrapperClassName, "TYPE", "Ljava/lang/Class;"));
} else {
codeClassForName(parameterTypes[i], dataoutputstream);
}
dataoutputstream.writeByte(83);
}

dataoutputstream.writeByte(182);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"));
dataoutputstream.writeByte(179);
dataoutputstream.writeShort(cp.getFieldRef(ProxyGenerator.dotToSlash(className), methodFieldName, "Ljava/lang/reflect/Method;"));
}

public String methodName;
public Class parameterTypes[];
public Class returnType;
public Class exceptionTypes[];
public Class fromClass;
public String methodFieldName;
final ProxyGenerator this$0;

private ProxyMethod(String s, Class aclass[], Class class1, Class aclass1[], Class class2) {
this$0 = ProxyGenerator.this;
// super();
methodName = s;
parameterTypes = aclass;
returnType = class1;
exceptionTypes = aclass1;
fromClass = class2;
methodFieldName = (new StringBuilder()).append("m").append(proxyMethodCount++).toString();
}

}

public static byte[] generateProxyClass(String s, Class aclass[]) {
ProxyGenerator proxygenerator = new ProxyGenerator(s, aclass);
byte abyte0[] = proxygenerator.generateClassFile();
if (saveGeneratedFiles)
AccessController.doPrivileged(new PrivilegedAction(s, abyte0) {

public Object run() {
try {
FileOutputStream fileoutputstream = new FileOutputStream((new StringBuilder()).append(ProxyGenerator.dotToSlash(name)).append(".class")
.toString());
fileoutputstream.write(classFile);
fileoutputstream.close();
return null;
} catch (IOException ioexception) {
throw new InternalError((new StringBuilder()).append("I/O exception saving generated file: ").append(ioexception).toString());
}
}

final String name;
final byte classFile[];

{
name = s;
classFile = abyte0;
super();
}
});
return abyte0;
}

private ProxyGenerator(String s, Class aclass[]) {
cp = new ConstantPool();
fields = new ArrayList();
methods = new ArrayList();
proxyMethods = new HashMap();
proxyMethodCount = 0;
className = s;
interfaces = aclass;
}
/**
* 获取字节文件的整体入口
* @return
*/
private byte[] generateClassFile() {
/**
* 添加三个方法
*/
addProxyMethod(hashCodeMethod, Object.class);
addProxyMethod(equalsMethod, Object.class);
addProxyMethod(toStringMethod, Object.class);
/**
* 添加接口中的方法
*/
for (int i = 0; i < interfaces.length; i++) {
Method amethod[] = interfaces[i].getMethods();
for (int k = 0; k < amethod.length; k++)
addProxyMethod(amethod[k], interfaces[i]);

}

List list;
for (Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext(); checkReturnTypes(list))
list = (List) iterator.next();

try {
methods.add(generateConstructor());//添加构造方法
for (Iterator iterator1 = proxyMethods.values().iterator(); iterator1.hasNext();) {
List list1 = (List) iterator1.next();
Iterator iterator2 = list1.iterator();
while (iterator2.hasNext()) {
ProxyMethod proxymethod = (ProxyMethod) iterator2.next();
fields.add(new FieldInfo(proxymethod.methodFieldName, "Ljava/lang/reflect/Method;", 10));
methods.add(proxymethod.generateMethod());
}
}

methods.add(generateStaticInitializer());
} catch (IOException ioexception) {
throw new InternalError("unexpected I/O Exception");
}
if (methods.size() > 65535)
throw new IllegalArgumentException("method limit exceeded");
if (fields.size() > 65535)
throw new IllegalArgumentException("field limit exceeded");
cp.getClass(dotToSlash(className));
cp.getClass("java/lang/reflect/Proxy");
for (int j = 0; j < interfaces.length; j++)
cp.getClass(dotToSlash(interfaces[j].getName()));

cp.setReadOnly();

ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);
try {
dataoutputstream.writeInt(-889275714);//写入魔数
dataoutputstream.writeShort(0);//此版本
dataoutputstream.writeShort(49);//主板本
cp.write(dataoutputstream);//写入常量池
dataoutputstream.writeShort(49);//访问标志
/**
* 类、父类、接口索引
*/
dataoutputstream.writeShort(cp.getClass(dotToSlash(className)));//获取类索引
dataoutputstream.writeShort(cp.getClass("java/lang/reflect/Proxy"));//获取父类索引
dataoutputstream.writeShort(interfaces.length);//接口数量
for (int l = 0; l < interfaces.length; l++)
dataoutputstream.writeShort(cp.getClass(dotToSlash(interfaces[l].getName())));//接口索引

dataoutputstream.writeShort(fields.size());
FieldInfo fieldinfo;
for (Iterator iterator3 = fields.iterator(); iterator3.hasNext(); fieldinfo.write(dataoutputstream))
fieldinfo = (FieldInfo) iterator3.next();

dataoutputstream.writeShort(methods.size());
MethodInfo methodinfo;
for (Iterator iterator4 = methods.iterator(); iterator4.hasNext(); methodinfo.write(dataoutputstream))
methodinfo = (MethodInfo) iterator4.next();

dataoutputstream.writeShort(0);
} catch (IOException ioexception1) {
throw new InternalError("unexpected I/O Exception");
}
return bytearrayoutputstream.toByteArray();
}

private void addProxyMethod(Method method, Class class1) {
String s;
Class aclass[];
Class class2;
Class aclass1[];
Object obj;
label0: {
s = method.getName();
aclass = method.getParameterTypes();
class2 = method.getReturnType();
aclass1 = method.getExceptionTypes();
String s1 = (new StringBuilder()).append(s).append(getParameterDescriptors(aclass)).toString();
obj = (List) proxyMethods.get(s1);
if (obj != null) {
Iterator iterator = ((List) (obj)).iterator();
ProxyMethod proxymethod;
do {
if (!iterator.hasNext())
break label0;
proxymethod = (ProxyMethod) iterator.next();
} while (class2 != proxymethod.returnType);
ArrayList arraylist = new ArrayList();
collectCompatibleTypes(aclass1, proxymethod.exceptionTypes, arraylist);
collectCompatibleTypes(proxymethod.exceptionTypes, aclass1, arraylist);
proxymethod.exceptionTypes = new Class[arraylist.size()];
proxymethod.exceptionTypes = (Class[]) arraylist.toArray(proxymethod.exceptionTypes);
return;
}
obj = new ArrayList(3);
proxyMethods.put(s1, obj);
}
((List) (obj)).add(new ProxyMethod(s, aclass, class2, aclass1, class1));
}

private static void checkReturnTypes(List list) {
if (list.size() < 2)
return;
LinkedList linkedlist = new LinkedList();
Iterator iterator = list.iterator();
label0: do {
if (!iterator.hasNext())
break;
ProxyMethod proxymethod1 = (ProxyMethod) iterator.next();
Class class1 = proxymethod1.returnType;
if (class1.isPrimitive())
throw new IllegalArgumentException((new StringBuilder()).append("methods with same signature ")
.append(getFriendlyMethodSignature(proxymethod1.methodName, proxymethod1.parameterTypes)).append(" but incompatible return types: ")
.append(class1.getName()).append(" and others").toString());
boolean flag = false;
ListIterator listiterator = linkedlist.listIterator();
do {
if (!listiterator.hasNext())
break;
Class class2 = (Class) listiterator.next();
if (class1.isAssignableFrom(class2)) {
if (!$assertionsDisabled && flag)
throw new AssertionError();
continue label0;
}
if (class2.isAssignableFrom(class1))
if (!flag) {
listiterator.set(class1);
flag = true;
} else {
listiterator.remove();
}
} while (true);
if (!flag)
linkedlist.add(class1);
} while (true);
if (linkedlist.size() > 1) {
ProxyMethod proxymethod = (ProxyMethod) list.get(0);
throw new IllegalArgumentException((new StringBuilder()).append("methods with same signature ")
.append(getFriendlyMethodSignature(proxymethod.methodName, proxymethod.parameterTypes)).append(" but incompatible return types: ")
.append(linkedlist).toString());
} else {
return;
}
}

private MethodInfo generateConstructor() throws IOException {
//构造方法 方法名称、方法参数、可见性
MethodInfo methodinfo = new MethodInfo("<init>", "(Ljava/lang/reflect/InvocationHandler;)V", 1);
DataOutputStream dataoutputstream = new DataOutputStream(methodinfo.code);
code_aload(0, dataoutputstream);
code_aload(1, dataoutputstream);
dataoutputstream.writeByte(183);
//调用父类的构造方法
dataoutputstream.writeShort(cp.getMethodRef("java/lang/reflect/Proxy", "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
dataoutputstream.writeByte(177);
methodinfo.maxStack = 10;
methodinfo.maxLocals = 2;
methodinfo.declaredExceptions = new short[0];
return methodinfo;
}
//类构造方法
private MethodInfo generateStaticInitializer() throws IOException {
MethodInfo methodinfo = new MethodInfo("<clinit>", "()V",;
int i = 1;
short word1 = 0;
DataOutputStream dataoutputstream = new DataOutputStream(methodinfo.code);
for (Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext();) {
List list = (List) iterator.next();
Iterator iterator1 = list.iterator();
while (iterator1.hasNext()) {
ProxyMethod proxymethod = (ProxyMethod) iterator1.next();
proxymethod.codeFieldInitialization(dataoutputstream);
}
}

dataoutputstream.writeByte(177);
short word0;
short word2 = word0 = (short) methodinfo.code.size();
methodinfo.exceptionTable.add(new ExceptionTableEntry(word1, word2, word0, cp.getClass("java/lang/NoSuchMethodException")));
code_astore(i, dataoutputstream);
dataoutputstream.writeByte(187);
dataoutputstream.writeShort(cp.getClass("java/lang/NoSuchMethodError"));
dataoutputstream.writeByte(89);
code_aload(i, dataoutputstream);
dataoutputstream.writeByte(182);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
dataoutputstream.writeByte(183);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V"));
dataoutputstream.writeByte(191);
word0 = (short) methodinfo.code.size();
methodinfo.exceptionTable.add(new ExceptionTableEntry(word1, word2, word0, cp.getClass("java/lang/ClassNotFoundException")));
code_astore(i, dataoutputstream);
dataoutputstream.writeByte(187);
dataoutputstream.writeShort(cp.getClass("java/lang/NoClassDefFoundError"));
dataoutputstream.writeByte(89);
code_aload(i, dataoutputstream);
dataoutputstream.writeByte(182);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
dataoutputstream.writeByte(183);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/NoClassDefFoundError", "<init>", "(Ljava/lang/String;)V"));
dataoutputstream.writeByte(191);
if (methodinfo.code.size() > 65535) {
throw new IllegalArgumentException("code size limit exceeded");
} else {
methodinfo.maxStack = 10;
methodinfo.maxLocals = (short) (i + 1);
methodinfo.declaredExceptions = new short[0];
return methodinfo;
}
}

/**
* 写入相应的字节码
*
* @param i
* @param dataoutputstream
* @throws IOException
*/
private void code_iload(int i, DataOutputStream dataoutputstream) throws IOException {
codeLocalLoadStore(i, 21, 26, dataoutputstream);
}

private void code_lload(int i, DataOutputStream dataoutputstream) throws IOException {
codeLocalLoadStore(i, 22, 30, dataoutputstream);
}

private void code_fload(int i, DataOutputStream dataoutputstream) throws IOException {
codeLocalLoadStore(i, 23, 34, dataoutputstream);
}

private void code_dload(int i, DataOutputStream dataoutputstream) throws IOException {
codeLocalLoadStore(i, 24, 38, dataoutputstream);
}

private void code_aload(int i, DataOutputStream dataoutputstream) throws IOException {
codeLocalLoadStore(i, 25, 42, dataoutputstream);
}

private void code_astore(int i, DataOutputStream dataoutputstream) throws IOException {
codeLocalLoadStore(i, 58, 75, dataoutputstream);
}

private void codeLocalLoadStore(int i, int j, int k, DataOutputStream dataoutputstream) throws IOException {
if (!$assertionsDisabled && (i < 0 || i > 65535))
throw new AssertionError();
if (i <= 3)
dataoutputstream.writeByte(k + i);
else if (i <= 255) {
dataoutputstream.writeByte(j);
dataoutputstream.writeByte(i & 255);
} else {
dataoutputstream.writeByte(196);
dataoutputstream.writeByte(j);
dataoutputstream.writeShort(i & 65535);
}
}

private void code_ldc(int i, DataOutputStream dataoutputstream) throws IOException {
if (!$assertionsDisabled && (i < 0 || i > 65535))
throw new AssertionError();
if (i <= 255) {
dataoutputstream.writeByte(18);
dataoutputstream.writeByte(i & 255);
} else {
dataoutputstream.writeByte(19);
dataoutputstream.writeShort(i & 65535);
}
}

private void code_ipush(int i, DataOutputStream dataoutputstream) throws IOException {
if (i >= -1 && i <= 5)
dataoutputstream.writeByte(3 + i);
else if (i >= -128 && i <= 127) {
dataoutputstream.writeByte(16);
dataoutputstream.writeByte(i & 255);
} else if (i >= -32768 && i <= 32767) {
dataoutputstream.writeByte(17);
dataoutputstream.writeShort(i & 65535);
} else {
throw new AssertionError();
}
}

private void codeClassForName(Class class1, DataOutputStream dataoutputstream) throws IOException {
code_ldc(cp.getString(class1.getName()), dataoutputstream);
dataoutputstream.writeByte(184);
dataoutputstream.writeShort(cp.getMethodRef("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;"));
}

private static String dotToSlash(String s) {
return s.replace('.', '/');
}

/**
* 返回方法描述符
*
* @param aclass
* @param class1
* @return
*/
private static String getMethodDescriptor(Class aclass[], Class class1) {
//参数描述符+返回类型描述符
return (new StringBuilder()).append(getParameterDescriptors(aclass)).append(class1 != Void.TYPE ? getFieldType(class1) : "V").toString();
}

/**
* 获取参数描述符
*
* @param aclass
* @return
*/
private static String getParameterDescriptors(Class aclass[]) {
StringBuilder stringbuilder = new StringBuilder("(");
for (int i = 0; i < aclass.length; i++)
stringbuilder.append(getFieldType(aclass[i]));

stringbuilder.append(')');
return stringbuilder.toString();
}

/**
* 返回类的描述符
*
* @param class1
* @return
*/
private static String getFieldType(Class class1) {
if (class1.isPrimitive())
return PrimitiveTypeInfo.get(class1).baseTypeString;
if (class1.isArray())
return class1.getName().replace('.', '/');
else
return (new StringBuilder()).append("L").append(dotToSlash(class1.getName())).append(";").toString();// 对象返回描述符
}

private static String getFriendlyMethodSignature(String s, Class aclass[]) {
StringBuilder stringbuilder = new StringBuilder(s);
stringbuilder.append('(');
for (int i = 0; i < aclass.length; i++) {
if (i > 0)
stringbuilder.append(',');
Class class1 = aclass[i];
int j;
for (j = 0; class1.isArray(); j++)
class1 = class1.getComponentType();

stringbuilder.append(class1.getName());
while (j-- > 0)
stringbuilder.append("[]");
}

stringbuilder.append(')');
return stringbuilder.toString();
}

private static int getWordsPerType(Class class1) {
return class1 != Long.TYPE && class1 != Double.TYPE ? 1 : 2;
}

private static void collectCompatibleTypes(Class aclass[], Class aclass1[], List list) {
label0: for (int i = 0; i < aclass.length; i++) {
if (list.contains(aclass[i]))
continue;
int j = 0;
do {
if (j >= aclass1.length)
continue label0;
if (aclass1[j].isAssignableFrom(aclass[i])) {
list.add(aclass[i]);
continue label0;
}
j++;
} while (true);
}

}

private static List computeUniqueCatchList(Class aclass[]) {
ArrayList arraylist = new ArrayList();
arraylist.add(Error.class);
arraylist.add(RuntimeException.class);
label0: for (int i = 0; i < aclass.length; i++) {
Class class1 = aclass[i];
if (class1.isAssignableFrom(Throwable.class)) {
arraylist.clear();
break;
}
if (!Throwable.class.isAssignableFrom(class1))
continue;
for (int j = 0; j < arraylist.size();) {
Class class2 = (Class) arraylist.get(j);
if (class2.isAssignableFrom(class1))
continue label0;
if (class1.isAssignableFrom(class2))
arraylist.remove(j);
else
j++;
}

arraylist.add(class1);
}

return arraylist;
}

/**
* 版本号
*/
private static final int CLASSFILE_MAJOR_VERSION = 49;// 主板本号
private static final int CLASSFILE_MINOR_VERSION = 0;// 此版本号
/**
* 标志位,存放在常量池种类
*/
private static final int CONSTANT_UTF8 = 1;
private static final int CONSTANT_UNICODE = 2;
private static final int CONSTANT_INTEGER = 3;
private static final int CONSTANT_FLOAT = 4;
private static final int CONSTANT_LONG = 5;
private static final int CONSTANT_DOUBLE = 6;
private static final int CONSTANT_CLASS = 7;
private static final int CONSTANT_STRING = 8;
private static final int CONSTANT_FIELD = 9;
private static final int CONSTANT_METHOD = 10;
private static final int CONSTANT_INTERFACEMETHOD = 11;
private static final int CONSTANT_NAMEANDTYPE = 12;
/**
* 访问标志
*/
private static final int ACC_PUBLIC = 1;
private static final int ACC_PRIVATE = 2;
private static final int ACC_STATIC = 8;
private static final int ACC_FINAL = 16;
private static final int ACC_SUPER = 32;
/**
* 指令。code属性里面的字节
*/
private static final int opc_aconst_null = 1;
private static final int opc_iconst_0 = 3;
private static final int opc_bipush = 16;
private static final int opc_sipush = 17;
private static final int opc_ldc = 18;
private static final int opc_ldc_w = 19;
private static final int opc_iload = 21;
private static final int opc_lload = 22;
private static final int opc_fload = 23;
private static final int opc_dload = 24;
private static final int opc_aload = 25;
private static final int opc_iload_0 = 26;
private static final int opc_lload_0 = 30;
private static final int opc_fload_0 = 34;
private static final int opc_dload_0 = 38;
private static final int opc_aload_0 = 42;
private static final int opc_astore = 58;
private static final int opc_astore_0 = 75;
private static final int opc_aastore = 83;
private static final int opc_pop = 87;
private static final int opc_dup = 89;
private static final int opc_ireturn = 172;
private static final int opc_lreturn = 173;
private static final int opc_freturn = 174;
private static final int opc_dreturn = 175;
private static final int opc_areturn = 176;
private static final int opc_return = 177;
private static final int opc_getstatic = 178;
private static final int opc_putstatic = 179;
private static final int opc_getfield = 180;
private static final int opc_invokevirtual = 182;
private static final int opc_invokespecial = 183;
private static final int opc_invokestatic = 184;
private static final int opc_invokeinterface = 185;
private static final int opc_new = 187;
private static final int opc_anewarray = 189;
private static final int opc_athrow = 191;
private static final int opc_checkcast = 192;
private static final int opc_wide = 196;

private static final String superclassName = "java/lang/reflect/Proxy";// 父类名称
private static final String handlerFieldName = "h";// 句柄名称
private static final boolean saveGeneratedFiles = ((Boolean) AccessController.doPrivileged(new GetBooleanAction(
"sun.misc.ProxyGenerator.saveGeneratedFiles"))).booleanValue();// 是否允许生成动态代理类
private static Method hashCodeMethod;
private static Method equalsMethod;
private static Method toStringMethod;
private String className;
private Class interfaces[];
private ConstantPool cp;// 常量池
private List fields;// 字段集合
private List methods;// 方法集合
private Map proxyMethods;
private int proxyMethodCount;
static final boolean $assertionsDisabled = !ProxyGenerator.class.desiredAssertionStatus();

static {
try {
hashCodeMethod = Object.class.getMethod("hashCode", new Class[0]);
equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class });
toStringMethod = Object.class.getMethod("toString", new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
}

}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics