|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/* |
|
|
|
|
* Copyright 2000-2015 JetBrains s.r.o. |
|
|
|
|
* Copyright 2000-2016 JetBrains s.r.o. |
|
|
|
|
* |
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -27,20 +27,21 @@ import org.jetbrains.java.decompiler.util.DataInputFullStream; |
|
|
|
|
import java.io.DataInputStream; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.BitSet; |
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
@SuppressWarnings("AssignmentToForLoopParameter") |
|
|
|
|
public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
|
|
|
|
|
public static final int FIELD = 1; |
|
|
|
|
public static final int METHOD = 2; |
|
|
|
|
|
|
|
|
|
private final List<PooledConstant> pool = new ArrayList<PooledConstant>(); |
|
|
|
|
private final List<PooledConstant> pool; |
|
|
|
|
private final PoolInterceptor interceptor; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ConstantPool(DataInputStream in) throws IOException { |
|
|
|
|
int size = in.readUnsignedShort(); |
|
|
|
|
int[] pass = new int[size]; |
|
|
|
|
pool = new ArrayList<PooledConstant>(size); |
|
|
|
|
BitSet[] nextPass = {new BitSet(size), new BitSet(size), new BitSet(size)}; |
|
|
|
|
|
|
|
|
|
// first dummy constant
|
|
|
|
|
pool.add(null); |
|
|
|
@ -53,54 +54,59 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
case CodeConstants.CONSTANT_Utf8: |
|
|
|
|
pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Utf8, in.readUTF())); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Integer: |
|
|
|
|
pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Integer, new Integer(in.readInt()))); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Float: |
|
|
|
|
pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Float, new Float(in.readFloat()))); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Long: |
|
|
|
|
pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Long, new Long(in.readLong()))); |
|
|
|
|
pool.add(null); |
|
|
|
|
i++; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Double: |
|
|
|
|
pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Double, new Double(in.readDouble()))); |
|
|
|
|
pool.add(null); |
|
|
|
|
i++; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Class: |
|
|
|
|
case CodeConstants.CONSTANT_String: |
|
|
|
|
case CodeConstants.CONSTANT_MethodType: |
|
|
|
|
pool.add(new PrimitiveConstant(tag, in.readUnsignedShort())); |
|
|
|
|
pass[i] = 1; |
|
|
|
|
nextPass[0].set(i); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_NameAndType: |
|
|
|
|
pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort())); |
|
|
|
|
nextPass[0].set(i); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Fieldref: |
|
|
|
|
case CodeConstants.CONSTANT_Methodref: |
|
|
|
|
case CodeConstants.CONSTANT_InterfaceMethodref: |
|
|
|
|
case CodeConstants.CONSTANT_NameAndType: |
|
|
|
|
case CodeConstants.CONSTANT_InvokeDynamic: |
|
|
|
|
pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort())); |
|
|
|
|
if (tag == CodeConstants.CONSTANT_NameAndType) { |
|
|
|
|
pass[i] = 1; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
pass[i] = 2; |
|
|
|
|
} |
|
|
|
|
nextPass[1].set(i); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_MethodHandle: |
|
|
|
|
pool.add(new LinkConstant(tag, in.readUnsignedByte(), in.readUnsignedShort())); |
|
|
|
|
pass[i] = 3; |
|
|
|
|
nextPass[2].set(i); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// resolving complex pool elements
|
|
|
|
|
for (int passIndex = 1; passIndex <= 3; passIndex++) { |
|
|
|
|
for (int i = 1; i < size; i++) { |
|
|
|
|
if (pass[i] == passIndex) { |
|
|
|
|
pool.get(i).resolveConstant(this); |
|
|
|
|
} |
|
|
|
|
for (BitSet pass : nextPass) { |
|
|
|
|
int idx = 0; |
|
|
|
|
while ((idx = pass.nextSetBit(idx + 1)) > 0) { |
|
|
|
|
pool.get(idx).resolveConstant(this); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -116,6 +122,7 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
case CodeConstants.CONSTANT_Utf8: |
|
|
|
|
in.readUTF(); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Integer: |
|
|
|
|
case CodeConstants.CONSTANT_Float: |
|
|
|
|
case CodeConstants.CONSTANT_Fieldref: |
|
|
|
@ -125,16 +132,19 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
case CodeConstants.CONSTANT_InvokeDynamic: |
|
|
|
|
in.discard(4); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Long: |
|
|
|
|
case CodeConstants.CONSTANT_Double: |
|
|
|
|
in.discard(8); |
|
|
|
|
i++; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_Class: |
|
|
|
|
case CodeConstants.CONSTANT_String: |
|
|
|
|
case CodeConstants.CONSTANT_MethodType: |
|
|
|
|
in.discard(2); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CodeConstants.CONSTANT_MethodHandle: |
|
|
|
|
in.discard(3); |
|
|
|
|
} |
|
|
|
@ -155,7 +165,7 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
className = oldClassName; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String newElement = interceptor.getName(className + " " + elementName + " " + descriptor); |
|
|
|
|
String newElement = interceptor.getName(className + ' ' + elementName + ' ' + descriptor); |
|
|
|
|
if (newElement != null) { |
|
|
|
|
elementName = newElement.split(" ")[1]; |
|
|
|
|
} |
|
|
|
@ -196,7 +206,7 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
ln.type == CodeConstants.CONSTANT_Methodref || |
|
|
|
|
ln.type == CodeConstants.CONSTANT_InterfaceMethodref)) { |
|
|
|
|
String newClassName = buildNewClassname(ln.classname); |
|
|
|
|
String newElement = interceptor.getName(ln.classname + " " + ln.elementname + " " + ln.descriptor); |
|
|
|
|
String newElement = interceptor.getName(ln.classname + ' ' + ln.elementname + ' ' + ln.descriptor); |
|
|
|
|
String newDescriptor = buildNewDescriptor(ln.type == CodeConstants.CONSTANT_Fieldref, ln.descriptor); |
|
|
|
|
|
|
|
|
|
if (newClassName != null || newElement != null || newDescriptor != null) { |
|
|
|
@ -220,10 +230,10 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
|
|
|
|
|
if (vt.arrayDim > 0) { |
|
|
|
|
for (int i = 0; i < vt.arrayDim; i++) { |
|
|
|
|
buffer.append("["); |
|
|
|
|
buffer.append('['); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer.append("L").append(newName).append(";"); |
|
|
|
|
buffer.append('L').append(newName).append(';'); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
buffer.append(newName); |
|
|
|
@ -243,4 +253,4 @@ public class ConstantPool implements NewClassNameBuilder { |
|
|
|
|
return MethodDescriptor.parseDescriptor(descriptor).buildNewDescriptor(this); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |