Skip to content

Commit

Permalink
修复问题 alibaba#253
Browse files Browse the repository at this point in the history
  • Loading branch information
dongchenxu committed Jan 9, 2020
1 parent 5f39822 commit 3ea7867
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 145 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.alibaba.jvm.sandbox.core.enhance.weaver;

import com.alibaba.jvm.sandbox.api.ProcessControlException;
import com.alibaba.jvm.sandbox.api.event.BeforeEvent;
import com.alibaba.jvm.sandbox.api.event.Event;
import com.alibaba.jvm.sandbox.api.event.ImmediatelyReturnEvent;
import com.alibaba.jvm.sandbox.api.event.ImmediatelyThrowsEvent;
import com.alibaba.jvm.sandbox.api.event.*;
import com.alibaba.jvm.sandbox.api.listener.EventListener;
import com.alibaba.jvm.sandbox.core.util.ObjectIDs;
import org.slf4j.Logger;
Expand All @@ -20,8 +17,10 @@
import static com.alibaba.jvm.sandbox.api.event.Event.Type.IMMEDIATELY_THROWS;
import static com.alibaba.jvm.sandbox.core.util.SandboxReflectUtils.isInterruptEventHandler;
import static java.com.alibaba.jvm.sandbox.spy.Spy.Ret.newInstanceForNone;
import static java.com.alibaba.jvm.sandbox.spy.Spy.Ret.newInstanceForThrows;
import static org.apache.commons.lang3.ArrayUtils.contains;
import static org.apache.commons.lang3.StringUtils.join;
import static org.apache.commons.lang3.StringUtils.swapCase;

/**
* 事件处理
Expand Down Expand Up @@ -94,23 +93,25 @@ private Spy.Ret handleEvent(final int listenerId,
final int invokeId,
final Event event,
final EventProcessor processor) throws Throwable {
// 获取事件监听器
final EventListener listener = processor.listener;

try {
// 如果当前事件不在事件监听器处理列表中,则直接返回,不处理事件
if (!contains(processor.eventTypes, event.type)) {
return newInstanceForNone();
}

if (contains(processor.eventTypes, event.type)) {
// 调用事件处理
listener.onEvent(event);
if (logger.isDebugEnabled()) {
logger.debug("on-event: event|{}|{}|{}|{}",
event.type,
processId,
invokeId,
listenerId
);
}
// 调用事件处理
try {
if (logger.isDebugEnabled()) {
logger.debug("on-event: event|{}|{}|{}|{}",
event.type,
processId,
invokeId,
listenerId
);
}

listener.onEvent(event);
}

// 代码执行流程变更
Expand All @@ -129,22 +130,15 @@ private Spy.Ret handleEvent(final int listenerId,
);

// 如果流程控制要求忽略后续处理所有事件,则需要在此处进行标记
// 标记当前线程中、当前EventListener中需要主动忽略的ProcessId
if (pce.isIgnoreProcessEvent()) {
process.markIgnoreProcessId(processId);
process.markIgnoreProcess();
}

switch (state) {

// 立即返回对象
case RETURN_IMMEDIATELY: {

// 如果在BeforeEvent处理过程中发生ProcessControl行为,将会造成堆栈错位
// 所以这里需要将错位的堆栈进行补齐
if (event instanceof BeforeEvent) {
process.popInvokeId();
}

// 如果已经禁止后续返回任何事件了,则不进行后续的操作
if (pce.isIgnoreProcessEvent()) {
logger.debug("on-event: event|{}|{}|{}|{}, ignore immediately-return-event, isIgnored.",
Expand All @@ -153,45 +147,19 @@ private Spy.Ret handleEvent(final int listenerId,
invokeId,
listenerId
);
return Spy.Ret.newInstanceForReturn(pce.getRespond());
}

// 如果没有注册监听ImmediatelyEvent事件,则不进行后续的操作
if (!contains(processor.eventTypes, IMMEDIATELY_RETURN)) {
logger.debug("on-event: event|{}|{}|{}|{}, ignore immediately-return-event, not contains.",
event.type,
processId,
invokeId,
listenerId
);
return Spy.Ret.newInstanceForReturn(pce.getRespond());
} else {
// 补偿立即返回事件
compensateProcessControlEvent(pce, processor, process, event);
}

// 这里需要补偿ImmediatelyEvent
final ImmediatelyReturnEvent immediatelyReturnEvent
= process
.getEventFactory()
.makeImmediatelyReturnEvent(processId, invokeId, pce.getRespond());

final Spy.Ret ret;
try {
ret = handleEvent(
listenerId,
processId,
invokeId,
immediatelyReturnEvent,
processor
);
} finally {
process.getEventFactory().returnEvent(immediatelyReturnEvent);
// 如果是在BEFORE中立即返回,则后续不会再有RETURN事件产生
// 这里需要主动对齐堆栈
if(event.type == Event.Type.BEFORE) {
process.popInvokeId();
}

if (ret.state == Spy.Ret.RET_STATE_NONE) {
return Spy.Ret.newInstanceForReturn(pce.getRespond());
} else {
// 如果不是,则返回最新的处理结果
return ret;
}
// 让流程立即返回
return Spy.Ret.newInstanceForReturn(pce.getRespond());

}

Expand All @@ -200,12 +168,6 @@ private Spy.Ret handleEvent(final int listenerId,

final Throwable throwable = (Throwable) pce.getRespond();

// 如果在BeforeEvent处理过程中发生ProcessControl行为,将会造成堆栈错位
// 所以这里需要将错位的堆栈进行补齐
if (event instanceof BeforeEvent) {
process.popInvokeId();
}

// 如果已经禁止后续返回任何事件了,则不进行后续的操作
if (pce.isIgnoreProcessEvent()) {
logger.debug("on-event: event|{}|{}|{}|{}, ignore immediately-throws-event, isIgnored.",
Expand All @@ -214,50 +176,25 @@ private Spy.Ret handleEvent(final int listenerId,
invokeId,
listenerId
);
return Spy.Ret.newInstanceForThrows(throwable);
}

// 如果没有注册监听ImmediatelyEvent事件,则不进行后续的操作
if (!contains(processor.eventTypes, IMMEDIATELY_THROWS)) {
logger.debug("on-event: event|{}|{}|{}|{}, ignore immediately-throws-event, not contains.",
event.type,
processId,
invokeId,
listenerId
);
return Spy.Ret.newInstanceForThrows(throwable);
}

// 如果已经禁止后续返回任何事件了,则不进行后续的操作
if (pce.isIgnoreProcessEvent()) {
return Spy.Ret.newInstanceForThrows(throwable);
}
} else {

final ImmediatelyThrowsEvent immediatelyThrowsEvent
= process
.getEventFactory()
.makeImmediatelyThrowsEvent(processId, invokeId, throwable);
// 如果是在BEFORE中立即抛出,则后续不会再有THROWS事件产生
// 这里需要主动对齐堆栈
if(event.type == Event.Type.BEFORE) {
process.popInvokeId();
}

// 标记本次异常由ImmediatelyException产生,让下次异常事件处理直接忽略
if (event.type != Event.Type.THROWS) {
process.markExceptionFromImmediately();
}

final Spy.Ret ret;
try {
ret = handleEvent(
listenerId,
processId,
invokeId,
immediatelyThrowsEvent,
processor
);
} finally {
process.getEventFactory().returnEvent(immediatelyThrowsEvent);
// 补偿立即抛出事件
compensateProcessControlEvent(pce, processor, process, event);
}

if (ret.state == Spy.Ret.RET_STATE_NONE) {
return Spy.Ret.newInstanceForThrows(throwable);
} else {
// 如果不是,则返回最新的处理结果
return ret;
}
// 让流程立即抛出
return Spy.Ret.newInstanceForThrows(throwable);

}

Expand Down Expand Up @@ -295,6 +232,56 @@ private Spy.Ret handleEvent(final int listenerId,
return newInstanceForNone();
}

// 补偿事件
// 随着历史版本的演进,一些事件已经过期,但为了兼容API,需要在这里进行补偿
private void compensateProcessControlEvent(ProcessControlException pce, EventProcessor processor, EventProcessor.Process process, Event event) {

// 核对是否需要补偿,如果目标监听器没监听过这类事件,则不需要进行补偿
if (!(event instanceof InvokeEvent)
|| !contains(processor.eventTypes, event.type)) {
return;
}

final InvokeEvent iEvent = (InvokeEvent) event;
final Event compensateEvent;

if (pce.getState() == ProcessControlException.State.RETURN_IMMEDIATELY
&& contains(processor.eventTypes, IMMEDIATELY_RETURN)) {
compensateEvent = process
.getEventFactory()
.makeImmediatelyReturnEvent(iEvent.processId, iEvent.invokeId, pce.getRespond());
} else if (pce.getState() == ProcessControlException.State.THROWS_IMMEDIATELY
&& contains(processor.eventTypes, IMMEDIATELY_THROWS)) {
compensateEvent = process
.getEventFactory()
.makeImmediatelyThrowsEvent(iEvent.processId, iEvent.invokeId, (Throwable) pce.getRespond());
} else {
return;
}

try {
logger.debug("compensate-event: event|{}|{}|{}|{} when ori-event:{}",
compensateEvent.type,
iEvent.processId,
iEvent.invokeId,
processor.listenerId,
event.type
);
processor.listener.onEvent(compensateEvent);
} catch (Throwable cause) {
logger.warn("compensate-event: event|{}|{}|{}|{} when ori-event:{} occur error.",
compensateEvent.type,
iEvent.processId,
iEvent.invokeId,
processor.listenerId,
event.type,
cause
);
} finally {
process.getEventFactory().returnEvent(compensateEvent);
}
}

/*
* 判断堆栈是否错位
*/
Expand All @@ -307,6 +294,7 @@ private boolean checkProcessStack(final int processId,

@Override
public Spy.Ret handleOnBefore(int listenerId, int targetClassLoaderObjectID, Object[] argumentArray, String javaClassName, String javaMethodName, String javaMethodDesc, Object target) throws Throwable {

// 获取事件处理器
final EventProcessor processor = mappingOfEventProcessor.get(listenerId);

Expand All @@ -319,19 +307,19 @@ public Spy.Ret handleOnBefore(int listenerId, int targetClassLoaderObjectID, Obj
// 获取调用跟踪信息
final EventProcessor.Process process = processor.processRef.get();

// 如果当前处理ID被忽略,则立即返回
if (process.isIgnoreProcess()) {
logger.debug("listener={} is marked ignore process!", listenerId);
return newInstanceForNone();
}

// 调用ID
final int invokeId = invokeIdSequencer.getAndIncrement();
process.pushInvokeId(invokeId);

// 调用过程ID
final int processId = process.getProcessId();

// 如果当前处理ID被忽略,则立即返回
if (process.touchIsIgnoreProcess(processId)) {
process.popInvokeId();
return newInstanceForNone();
}

final ClassLoader javaClassLoader = ObjectIDs.instance.getObject(targetClassLoaderObjectID);
final BeforeEvent event = process.getEventFactory().makeBeforeEvent(
processId,
Expand Down Expand Up @@ -383,9 +371,22 @@ private Spy.Ret handleOnEnd(final int listenerId,
return newInstanceForNone();
}

// 如果异常来自于ImmediatelyException,则忽略处理直接返回抛异常
final boolean isExceptionFromImmediately = !isReturn && process.rollingIsExceptionFromImmediately();
if (isExceptionFromImmediately) {
return newInstanceForThrows((Throwable) object);
}

// 继续异常处理
final int processId = process.getProcessId();
final int invokeId = process.popInvokeId();

// 忽略事件处理
// 放在stack.pop()后边是为了对齐执行栈
if (process.isIgnoreProcess()) {
return newInstanceForNone();
}

// 如果PID==IID说明已经到栈顶,此时需要核对堆栈是否为空
// 如果不为空需要输出日志进行告警
if (checkProcessStack(processId, invokeId, process.isEmptyStack())) {
Expand All @@ -396,12 +397,6 @@ private Spy.Ret handleOnEnd(final int listenerId,
);
}

// 忽略事件处理
// 放在stack.pop()后边是为了对齐执行栈
if (process.touchIsIgnoreProcess(processId)) {
return newInstanceForNone();
}

final Event event = isReturn
? process.getEventFactory().makeReturnEvent(processId, invokeId, object)
: process.getEventFactory().makeThrowsEvent(processId, invokeId, (Throwable) object);
Expand Down Expand Up @@ -438,7 +433,7 @@ public void handleOnCallBefore(int listenerId, int lineNumber, String owner, Str
final int invokeId = process.getInvokeId();

// 如果事件处理流被忽略,则直接返回,不产生后续事件
if (process.touchIsIgnoreProcess(processId)) {
if (process.isIgnoreProcess()) {
return;
}

Expand Down Expand Up @@ -469,7 +464,7 @@ public void handleOnCallReturn(int listenerId) throws Throwable {
final int invokeId = process.getInvokeId();

// 如果事件处理流被忽略,则直接返回,不产生后续事件
if (process.touchIsIgnoreProcess(processId)) {
if (process.isIgnoreProcess()) {
return;
}

Expand Down Expand Up @@ -500,7 +495,7 @@ public void handleOnCallThrows(int listenerId, String throwException) throws Thr
final int invokeId = process.getInvokeId();

// 如果事件处理流被忽略,则直接返回,不产生后续事件
if (process.touchIsIgnoreProcess(processId)) {
if (process.isIgnoreProcess()) {
return;
}

Expand Down Expand Up @@ -534,7 +529,7 @@ public void handleOnLine(int listenerId, int lineNumber) throws Throwable {
final int invokeId = process.getInvokeId();

// 如果事件处理流被忽略,则直接返回,不产生后续事件
if (process.touchIsIgnoreProcess(processId)) {
if (process.isIgnoreProcess()) {
return;
}

Expand Down
Loading

0 comments on commit 3ea7867

Please sign in to comment.