Fixed the case of using 'this' before throw in constructor
This commit is contained in:
+11
-6
@@ -302,6 +302,8 @@ public class InterceptionInstrumenter {
|
|||||||
mv = getDumpingVisitorWrapper(mv, name, desc);
|
mv = getDumpingVisitorWrapper(mv, name, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean isConstructor = "<init>".equals(name);
|
||||||
|
|
||||||
final int finalMaxParamCount = maxParamCount;
|
final int finalMaxParamCount = maxParamCount;
|
||||||
return new MethodVisitorWithUniversalHandler(ASM4, mv) {
|
return new MethodVisitorWithUniversalHandler(ASM4, mv) {
|
||||||
|
|
||||||
@@ -331,7 +333,9 @@ public class InterceptionInstrumenter {
|
|||||||
if (enterDataWritten) return;
|
if (enterDataWritten) return;
|
||||||
enterDataWritten = true;
|
enterDataWritten = true;
|
||||||
for (MethodData methodData : enterData) {
|
for (MethodData methodData : enterData) {
|
||||||
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, "<init>".equals(name));
|
// At the very beginning of a constructor, i.e. before any super() call, 'this' is not available
|
||||||
|
// It's too hard to detect a place right after the super() call, so we just put null instead of 'this' in such cases
|
||||||
|
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, isConstructor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +351,9 @@ public class InterceptionInstrumenter {
|
|||||||
case ARETURN:
|
case ARETURN:
|
||||||
case ATHROW:
|
case ATHROW:
|
||||||
for (MethodData methodData : exitData) {
|
for (MethodData methodData : exitData) {
|
||||||
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, false);
|
// A constructor may throw before calling super(), 'this' is not available in this case
|
||||||
|
boolean beforeThrowInConstructor = opcode == ATHROW && isConstructor;
|
||||||
|
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, beforeThrowInConstructor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -398,7 +404,7 @@ public class InterceptionInstrumenter {
|
|||||||
String instrumentedMethodDesc,
|
String instrumentedMethodDesc,
|
||||||
InstructionAdapter ia,
|
InstructionAdapter ia,
|
||||||
MethodData methodData,
|
MethodData methodData,
|
||||||
boolean constructorEntryPoint
|
boolean thisUnavailable
|
||||||
) {
|
) {
|
||||||
FieldData field = methodData.getOwnerField();
|
FieldData field = methodData.getOwnerField();
|
||||||
ia.getstatic(field.getDeclaringClass(), field.getName(), field.getDesc());
|
ia.getstatic(field.getDeclaringClass(), field.getName(), field.getDesc());
|
||||||
@@ -412,10 +418,9 @@ public class InterceptionInstrumenter {
|
|||||||
int parameterOffset = 0;
|
int parameterOffset = 0;
|
||||||
for (int i = 0; i < parameterCount; i++) {
|
for (int i = 0; i < parameterCount; i++) {
|
||||||
if (i == methodData.getThisParameterIndex()) {
|
if (i == methodData.getThisParameterIndex()) {
|
||||||
if (isStatic || constructorEntryPoint) {
|
if (isStatic || thisUnavailable) {
|
||||||
// a) static method, 'this' is null
|
// a) static method, 'this' is null
|
||||||
// b) At the very beginning of a constructor, i.e. before any super() call, 'this' is not available
|
// b) this is not available (some locations in constructors
|
||||||
// It's too hard to detect a place right after the super() call, so we just put null instead of 'this' in such cases
|
|
||||||
ia.aconst(null);
|
ia.aconst(null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user