You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Byteman COMPILE选项触发VerifyError,求排查规则问题

问题描述

在Felix Server中运行应用时,需要监控RestMonitoringJobRegistry.updateMonitoredState方法的执行时间,编写了两个带COMPILE选项的Byteman规则:入口记录开始时间,出口计算耗时。规则提交无报错,但运行时触发VerifyError,移除COMPILE选项后规则运行正常。

应用代码

package com.mypackage.monitoring.client;

public class RestMonitoringJobRegistry extends BaseMonitoringJobRegistry
{           
    public synchronized <T> void updateMonitoredState(
            MonitoringJob<T> aInMonitoringJob, T aInState)
    {
        if (aInMonitoringJob == null || aInState == null)
        {
            TPAResources.debug(logger,
                    "Cannot send: missing required information.");
            return;
        }

        // 省略其他逻辑
    }
}

入口规则

RULE record_startTime_RestMonitoringJobRegistry
CLASS com.mypackage.monitoring.client.RestMonitoringJobRegistry
METHOD updateMonitoredState
COMPILE
AT ENTRY
BIND
    LOGGER:Logger = com.mypackage.monitoring.client.RestMonitoringJobRegistry.logger;
    startTime = System.currentTimeMillis()
IF true
DO
    LOGGER.info("[JA] AT ENTRY");
    link(Thread.currentThread(), "startTime", startTime);
ENDRULE

出口规则

RULE check_duration_RestMonitoringJobRegistry
CLASS com.mypackage.monitoring.client.RestMonitoringJobRegistry
METHOD updateMonitoredState
COMPILE
AT EXIT
BIND
    LOGGER:Logger = com.mypackage.monitoring.client.RestMonitoringJobRegistry.logger;
    startTime:int = unlink(Thread.currentThread(), "startTime");
    endTime = System.currentTimeMillis()
IF true
DO
    LOGGER.info("[JA] AT EXIT: updateMonitoredState took elapsedTime [" + (endTime - startTime) + "] $aInMonitoringJob.getKey() [" + $aInMonitoringJob.getKey() +"]");
ENDRULE

错误日志

{"host":"host","level":"ERROR","log":{"classname":"com.pkg.as.service.log.impl.asrlog.Stdout2Log4jOutputStream$StdoutRedirectorThread:104","message":"check_duration_RestMonitoringJobRegistry : java.lang.VerifyError: (class: org/jboss/byteman/rule/helper/Helper_HelperAdapter_Compiled_53, method: execute0 signature: ()V) Expecting to find integer on stack","stacktrace":"","threadname":"StdoutThread"},"process":"run","service":"","time":"2024-03-22T00:20:50.725Z","timezone":"Asia/Kolkata","type":"log"}

移除COMPILE后的正常日志

{"host":"host","level":"INFO","log":{"classname":"org.jboss.byteman.rule.helper.Helper_HelperAdapter_Compiled_51:11","message":"[JA] AT ENTRY","stacktrace":"","threadname":"MonitoringJobRegistry-4"},"process":"execute0","service":"","time":"2024-03-22T00:20:30.714Z","timezone":"Asia/Kolkata","type":"log"}
问题分析与解决

问题出在类型不匹配:

  • 入口规则中System.currentTimeMillis()返回long类型,通过link绑定到线程的startTime是long值。
  • 出口规则错误地将startTime声明为int类型,unlink取出的long值被强制转换为int,在COMPILE模式下,Byteman生成的字节码严格遵循类型校验,栈上实际是long类型却被当作int处理,触发VerifyError。
  • 移除COMPILE选项后,Byteman使用解释模式执行规则,对类型校验相对宽松,隐式处理了类型转换,因此无报错。

修正后的规则

将startTime的类型统一为long,同时建议入口规则也显式声明类型保持一致:

修正后的入口规则

RULE record_startTime_RestMonitoringJobRegistry
CLASS com.mypackage.monitoring.client.RestMonitoringJobRegistry
METHOD updateMonitoredState
COMPILE
AT ENTRY
BIND
    LOGGER:Logger = com.mypackage.monitoring.client.RestMonitoringJobRegistry.logger;
    startTime:long = System.currentTimeMillis()
IF true
DO
    LOGGER.info("[JA] AT ENTRY");
    link(Thread.currentThread(), "startTime", startTime);
ENDRULE

修正后的出口规则

RULE check_duration_RestMonitoringJobRegistry
CLASS com.mypackage.monitoring.client.RestMonitoringJobRegistry
METHOD updateMonitoredState
COMPILE
AT EXIT
BIND
    LOGGER:Logger = com.mypackage.monitoring.client.RestMonitoringJobRegistry.logger;
    startTime:long = unlink(Thread.currentThread(), "startTime");
    endTime:long = System.currentTimeMillis()
IF true
DO
    LOGGER.info("[JA] AT EXIT: updateMonitoredState took elapsedTime [" + (endTime - startTime) + "] $aInMonitoringJob.getKey() [" + $aInMonitoringJob.getKey() +"]");
ENDRULE

内容的提问来源于stack exchange,提问作者Asif Ansari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:11:03