package org.nutz.lang.util;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.nutz.Nutz;
import org.nutz.log.Log;
import org.nutz.log.Logs;
public class ClassTools {
private static final Log log = Logs.get();
/**
* 从输入流中读取Class的名字,输入流必须是Class文件格式
*/
public static String getClassName(InputStream in) {
try {
DataInputStream dis = new DataInputStream(new BufferedInputStream(in));
Map<Integer, String> strs = new HashMap<Integer, String>();
Map<Integer, Integer> classes = new HashMap<Integer, Integer>();
dis.skipBytes(4);//Magic
dis.skipBytes(2);//副版本号
dis.skipBytes(2);//主版本号
//读取常量池
int constant_pool_count = dis.readUnsignedShort();
for (int i = 0; i < (constant_pool_count - 1); i++) {
byte flag = dis.readByte();
switch (flag) {
case 7://CONSTANT_Class:
int index = dis.readUnsignedShort();
classes.put(i+1, index);
break;
case 9://CONSTANT_Fieldref:
case 10://CONSTANT_Methodref:
case 11://CONSTANT_InterfaceMethodref:
dis.skipBytes(2);
dis.skipBytes(2);
break;
case 8://CONSTANT_String:
dis.skipBytes(2);
break;
case 3://CONSTANT_Integer:
case 4://CONSTANT_Float:
dis.skipBytes(4);
break;
case 5://CONSTANT_Long:
case 6://CONSTANT_Double:
dis.skipBytes(8);
i++;//必须跳过一个,这是class文件设计的一个缺陷,历史遗留问题
break;
case 12://CONSTANT_NameAndType:
dis.skipBytes(2);
dis.skipBytes(2);
break;
case 1://CONSTANT_Utf8:
int len = dis.readUnsignedShort();
byte[] data = new byte[len];
dis.readFully(data);
strs.put(i + 1, new String(data, "UTF-8"));//必然是UTF8的
break;
case 15://CONSTANT_MethodHandle:
dis.skipBytes(1);
dis.skipBytes(2);
break;
case 16://CONSTANT_MethodType:
dis.skipBytes(2);
break;
case 18://CONSTANT_InvokeDynamic:
dis.skipBytes(2);
dis.skipBytes(2);
break;
default:
throw new RuntimeException("Impossible!! flag="+flag);
}
}
dis.skipBytes(2);//版本控制符
int pos = dis.readUnsignedShort();
String name = strs.get(classes.get(pos));
if (name != null)
name = name.replace('/', '.');
dis.close();
return name;
} catch (Throwable e) {
if (log.isInfoEnabled())
log.info("Fail to read ClassName from class InputStream", e);
}
return null;
}
private static ClassLoader nutClassLoader;
static {
nutClassLoader = Nutz.class.getClassLoader();
//当使用JavaSE是,如果Nutz通过bootClassLoader加载,那么就会为null
if (nutClassLoader == null)
try {
nutClassLoader = ClassLoader.getSystemClassLoader();
}catch (Throwable e) {}
}
/**
* 获取nutz.jar的ClassLoader的方法
*/
public static ClassLoader getClassLoader() {
return nutClassLoader;
}
@Deprecated
public static void setNutClassLoader(ClassLoader nutClassLoader) {
ClassTools.nutClassLoader = nutClassLoader;
}
}