byte-buddy
byte-buddy copied to clipboard
Use OnMethodEnter can not access complex object
In my java code
class KnowledgeSmsAdvice{
private static final WechatMiniappFeature wechatMiniappFeature = new WechatMiniappFeatureImpl();
@Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Origin Method method,
@Advice.Argument(value = 0, optional = true, readOnly = false, typing = Assigner.Typing.DYNAMIC) Object argument) {
if (argument == null) return;
***
final String wechatMiniappName = wechatMiniappFeature.getWechatMiniappName(hospitalId);
***
}
}
In my premain class
public class PremainClass {
public static void premain(String args, Instrumentation instrumentation) {
Profile.inti(args);
//
AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, module, protectionDomain) ->
builder.method(ElementMatchers.named("sendLoopMessageTask")).intercept(Advice.to(KnowledgeSmsAdvice.class));
new AgentBuilder.Default()
.type(ElementMatchers.named("com.companies.message.interfaces.controller.MessageTaskController"))
.transform(transformer)
.installOn(instrumentation);
}
}
but when i access sendLoopMessageTask
this method get a exception
Handler dispatch failed; nested exception is java.lang.IllegalAccessError: tried to access field com.ipharmacare.mvp.agent.message.center.advice.KnowledgeSmsAdvice.wechatMiniappFeature from class com.companies.message.interfaces.controller.MessageTaskController
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.IllegalAccessError: tried to access field com.ipharmacare.mvp.agent.message.center.advice.KnowledgeSmsAdvice.wechatMiniappFeature from class com.companies.message.interfaces.controller.MessageTaskController
why goto access com.companies.message.interfaces.controller.MessageTaskController.wechatMiniappFeature
I think this is because your advice class and the field wechatMiniappFeature
are not declared as public
.
As pointed out, the code is more or less copy pasted. You can change this if you set inline = false
by delegation. But you are responsible to make sure that the targeted code is visible, or that the accessed code is visible from the inlined block.
PremainClass
java code
public class PremainClass {
public static void premain(String args, Instrumentation instrumentation) {
Profile.inti(args);
AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, module, protectionDomain) ->
builder.method(ElementMatchers.named("sendLoopMessageTask")).intercept(Advice.to(KnowledgeSmsAdvice.class));
new AgentBuilder.Default()
.type(ElementMatchers.named("com.companies.message.interfaces.controller.MessageTaskController"))
.transform(transformer)
.installOn(instrumentation);
}
}
KnowledgeSmsAdvice
java code
public class KnowledgeSmsAdvice {
private static final String knowledgeSceneCode = "HOSPITAL_KNOWLEDGE_SMS";
private static final WechatMiniappFeature wechatMiniappFeature = new WechatMiniappFeatureImpl();
@Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Origin Method method,
@Advice.Argument(value = 0, optional = true, readOnly = false, typing = Assigner.Typing.DYNAMIC)
Object argument) {
if (argument == null) return;
JSONObject reqJSON = JSON.parseObject(JSON.toJSONString(argument));
String sceneCode = StringUtils.trimToNull(reqJSON.getString("sceneCode"));
if (!StringUtils.equals(sceneCode, knowledgeSceneCode)) return;
Long hospitalId = reqJSON.getLong("hospitalId");
if (hospitalId == null) return;
final String wechatMiniappName = wechatMiniappFeature.getWechatMiniappName(hospitalId);
if (wechatMiniappName == null) return;
final String targetSceneCode = WechatMiniappName.generateMessageScene(wechatMiniappName,
knowledgeSceneCode);
reqJSON.put("sceneCode", targetSceneCode);
}
}
agent method MessageTaskController
java code
@RequestMapping({"/provider/message/task/client"})
@RestController
public class MessageTaskController {
private static final Logger log = LoggerFactory.getLogger(MessageTaskController.class);
@Autowired
MessageTaskService messageTaskService;
@Autowired
MessagePushWithJiGuangService messagePushWithJiGuangService;
@PostMapping({"/sendLoopMessageTask"})
public ServerResponse<String> sendLoopMessageTask(@RequestBody MessageTaskLoopVO messageTaskLoopVO) throws Exception {
return ServerResponse.createBySuccess(this.messageTaskService.saveLoopMessageTask(messageTaskLoopVO));
}
}
when i access sendLoopMessageTask
method get a exception
@raphw
As shown in the code above. Accessing the knowledgeSceneCode
field was successful, but the wechatMiniappFeature
field would result in an error
@raphw
This is because final strings (and primitives) are inlined. The field access is eliminated by javac.
You should change the annotation @advice.onMethodenter
to@advice.onMethodente (inline = false)