你好我一直试图找出这个错误很长一段时间了。我有一个nullpointer的新问题,这里是类:
编辑:该程序旨在将代码注入另一个类,以阻止它在加载时删除类,然后它反映类文件(存储为字节数组),然后转储到类文件。
我已经评论了与堆栈跟踪相对应的行号
public class Program {
private HashMap<String, ClassGen> myClass = new HashMap<String, ClassGen>();
private int array_index;
/**
* Constructor.
*/
public Program() {
try {
File Jar1 = new File("Jar1.jar");
File nJar1 = new File("nJar1.jar");
File OutPutJar = new File("Out.jar");
BAppletStub stub = new BAppletStub();
injectLoader();
dumpClientFiles(stub); // Line 65
JarFile theJar = new JarFile(OutPutJar);
Enumeration<?> en = theJar.entries();
while (en.hasMoreElements()) {
JarEntry entry = (JarEntry) en.nextElement();
if (entry.getName().endsWith(".class")) {
ClassParser cp = new ClassParser(theJar.getInputStream(entry), entry.getName());
JavaClass jc = cp.parse();
ClassGen cg = new ClassGen(jc);
myClass.put(cg.getClassName(), cg);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void injectLoader() throws IOException {
JarFile theJar = new JarFile("Jar1.jar");
FileOutputStream stream = new FileOutputStream("nJar1.jar");
JarOutputStream out = new JarOutputStream(stream);
Enumeration<?> en = theJar.entries();
while (en.hasMoreElements()) {
JarEntry entry = (JarEntry) en.nextElement();
if (entry.getName().contains("META-INF"))
continue;
JarEntry je = new JarEntry(entry.getName());
out.putNextEntry(je);
if (entry.getName().endsWith(".class")) {
ClassParser cp = new ClassParser(theJar.getInputStream(entry), entry.getName());
JavaClass jc = cp.parse();
ClassGen cg = new ClassGen(jc);
fixClass(cg);
out.write(cg.getJavaClass().getBytes());
} else {
InputStream in = theJar.getInputStream(entry);
int read;
byte[] buffer = new byte[1024];
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
}
out.close();
stream.close();
}
@SuppressWarnings({ "deprecation", "unchecked" })
private void fixClass(ClassGen cg) {
for (Method m : cg.getMethods()) {
if (m.getReturnType().equals(Type.CLASS)) {
MethodGen mg = new MethodGen(m, cg.getClassName(), cg.getConstantPool());
InstructionList list = mg.getInstructionList();
String pattern = "aaload checkcast aload invokevirtual";
InstructionFinder finder = new InstructionFinder(list);
Iterator<InstructionHandle[]> it = finder.search(pattern);
while (it.hasNext()) {
InstructionHandle[] handles = it.next();
INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) handles[3].getInstruction();
if (invoke.getMethodName(cg.getConstantPool()).equals("remove") && invoke.getClassName(cg.getConstantPool()).contains("Hashtable")) {
InstructionFactory factory = new InstructionFactory(cg);
Instruction i = factory.createInvoke("java/util/Hashtable", "get", invoke.getReturnType(cg.getConstantPool()), invoke.getArgumentTypes(cg.getConstantPool()), Constants.INVOKEVIRTUAL);
InstructionHandle handle = list.insert(handles[3], i);
InstructionHandle h = handles[3];
if (h.hasTargeters()) {
for (InstructionTargeter t : h.getTargeters()) {
t.updateTarget(h, handle);
}
}
try {
list.delete(h);
} catch (TargetLostException e) {
e.printStackTrace();
}
mg.setMaxLocals();
mg.setMaxStack();
cg.replaceMethod(m, mg.getMethod());
return;
}
}
}
}
}
private void dumpClientFiles(BAppletStub stub) {
try {
File f = new File("nJar1.jar");
URLClassLoader loader = new URLClassLoader(new URL[] { f.toURI().toURL() });
Class<?> g = loader.loadClass("Rs2Applet");
final Applet a = (Applet) g.newInstance();
a.setStub(stub);
a.init();
Object[] objs = getObjects(g, a); // Line 237
if (objs == null)
System.exit(1);
Hashtable<?, ?> tempTable = (Hashtable<?, ?>) objs[array_index];
JarOutputStream out = new JarOutputStream(new FileOutputStream("Out.jar"));
Enumeration<?> it = tempTable.keys();
int classes_dumped = 0;
while (it.hasMoreElements()) {
String s = (String) it.nextElement();
Object o = tempTable.get(s);
JarEntry entry = new JarEntry(s.replace(".", "/") + ".class");
out.putNextEntry(entry);
out.write((byte[]) o);
out.closeEntry();
classes_dumped++;
}
System.out.println("Dumped " + classes_dumped + " classes to Out.jar");
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public Object[] getObjects(Class<?> clazz, Object object) throws IllegalArgumentException, IllegalAccessException {
Field fd = null;
Field arr = null;
for (Field field : clazz.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.PRIVATE) != 0 && field.getType().getCanonicalName().equals("java.lang.Object[]")) {
if (fd == null) {
fd = field;
} else {
arr = field;
}
}
}
Object[] objs = null;
boolean found = false;
Field array_field = null;
outer: for (int i = 0; i < 2 && !found; i++) {
array_field = (array_field == null || array_field == arr) ? fd : arr;
if (!array_field.isAccessible()) { //Line 278
array_field.setAccessible(true);
}
objs = (Object[]) array_field.get(object);
for (int j = 0; j < objs.length; j++) {
Object o = objs[j];
if (o instanceof Hashtable) {
found = true;
if (((Hashtable<?, ?>) o).values().iterator().next().getClass().getCanonicalName().equals("byte[]")) {
array_index = j;
break outer;
}
}
}
}
if (fd.isAccessible())
fd.setAccessible(false);
if (arr.isAccessible())
arr.setAccessible(false);
return objs;
}
public static void main(String[] args) {
new Program(); //Line 304
}
}
这是堆栈跟踪:
java.lang.NullPointerException
at org.nick.program.getObjects(program.java:278)
at org.nick.program.dumpFiles(program.java:237)
at org.nick.program.<init>(program.java:65)
at org.nick.program.main(program.java:304)
我的问题是导致nullpointer的原因是什么?我怎么能纠正它?
答案 0 :(得分:5)
如果clazz
不包含Object[]
类型的任何私有字段(并且完全 Object[]
!类型擦除可能会起作用,但继承不会t),fd
和arr
都不会被设置。设置array_field
的行假设如果未设置arr
,则fd
将是 - 但在刚才提到的情况下,它不会。
至于如何解决它...好吧,这取决于你究竟想要做什么。这段代码对我来说没什么意义,所以对应该做什么的描述会有很大的帮助。
答案 1 :(得分:1)
您的代码中有许多方法可能导致此NullPointerException
。
例如,在第5行:
field.getType().getCanonicalName().equals
可能会导致此问题,因为getCanonicalName
可能会返回null
,在这种情况下最好的方法是使用:
"java.lang.Object[]".equals(field.getType().getCanonicalName())
虽然这不是问题,但您必须使用如上所示的防御性编程(或至少检查nulls
)。