arthas icon indicating copy to clipboard operation
arthas copied to clipboard

Enhance error! exception: java.lang.NoClassDefFoundError: class names don't match

Open newweapon opened this issue 4 years ago • 14 comments

  • [x] 我已经在 issues 里搜索,没有重复的issue。

环境信息

  • Arthas 版本: 3.3.3
  • 操作系统版本: macos 10.15.5
  • 目标进程的JVM版本: 1.8.0_212

java version "1.8.0_212" Java(TM) SE Runtime Environment (build 1.8.0_212-b10) Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)

  • 执行arthas-boot的方式: java -jar arthas-boot.jar

重现问题的步骤

  1. 启动demo程序(基于Springboo的web应用,jar方式启动)
  2. 启动arthas:java -jar arthas-boot.jar
  3. 执行jad命令能正常反编译代码: jad --source-only com.faceless.springbootdemo.web.controller.BookController
  4. 执行watch命令(确认包和类名无误): watch com.faceless.springbootdemo.web.controller.BookController findBook "{params,returnObj}" -x 2 提示无法enhance的异常。

期望的结果

显示正常watch结果。

实际运行的结果

watch命令无法得到正常监控结果。提示无法enhance的异常:

[arthas@40827]$ watch com.faceless.springbootdemo.web.controller.BookController findBook "{params,returnObj}" -x 2
Affect(class count: 1 , method count: 1) cost in 31 ms, listenerId: 9
Enhance error! exception: java.lang.NoClassDefFoundError: class names don't match, check arthas log: /Users/weiping/logs/arthas/arthas.log

arthas.log对应的日志为:

2020-06-19 20:51:31 [as-command-execute-daemon] INFO  c.t.arthas.core.advisor.Enhancer -enhance matched classes: [class com.faceless.springbootdemo.web.controller.BookController]
2020-06-19 20:51:31 [as-command-execute-daemon] ERROR c.t.arthas.core.advisor.Enhancer -Enhancer error, matchingClasses: [class com.faceless.springbootdemo.web.controller.BookController]
java.lang.NoClassDefFoundError: class names don't match
        at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
        at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
        at com.taobao.arthas.core.advisor.Enhancer.enhance(Enhancer.java:366)
        at com.taobao.arthas.core.command.monitor200.EnhancerCommand.enhance(EnhancerCommand.java:135)
        at com.taobao.arthas.core.command.monitor200.EnhancerCommand.process(EnhancerCommand.java:87)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
        at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:372)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

附:测试类BookController的代码:

package com.faceless.springbootdemo.web.controller;

@RestController
@RequestMapping("/api/v1")
@Slf4j
public class BookController {

    @Autowired
    private BookDao bookDao;

    @GetMapping(value="/book/{id}")
    public Result findBook(@PathVariable("id") Integer id) {
        Optional<Book> bookOptional = bookDao.findOne(id);
        if (bookOptional.isPresent()) {
            log.debug("Found the book: {}", bookOptional.get().toString());
            return Result.succ(bookOptional.get());
        } else {
            return Result.fail("Book NOT found. id=" + id);
        }
    }

}

newweapon avatar Jun 19 '20 14:06 newweapon

可以提交一个可运行的 demo不?能重现比较好排查

hengyunabc avatar Jun 20 '20 09:06 hengyunabc

我也有这个问题,你是怎么解决的?

ShawshankLin avatar Aug 27 '20 15:08 ShawshankLin

我也有这个问题,你是怎么解决的?

可以提供一个可执行demo不?

hengyunabc avatar Aug 27 '20 15:08 hengyunabc

遇到了相同的问题,jad反编译时方法里面有错误提示:

    /*
     * Exception decompiling
     */
    @Override
    @Metrics(logInput=true)
    public Result queryMain(SearchMainParams mainParams) {
        /*
         * This method has failed to decompile.  When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file.
         * org.benf.cfr.reader.util.ConfusedCFRException: Tried to end blocks [0[TRYBLOCK]], but top level block is 13[CATCHBLOCK]
         * org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.processEndingBlocks(Op04StructuredStatement.java:429)
         * org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.buildNestedBlocks(Op04StructuredStatement.java:478)
         * org.benf.cfr.reader.bytecode.analysis.opgraph.Op03SimpleStatement.createInitialStructuredBlock(Op03SimpleStatement.java:728)
         * org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:806)
         * org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:258)
         * org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:192)
         * org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:94)
         * org.benf.cfr.reader.entities.Method.analyse(Method.java:521)
         * org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1035)
         * org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:922)
         * org.benf.cfr.reader.Driver.doClass(Driver.java:83)
         * org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:67)
         * com.taobao.arthas.core.util.Decompiler.decompile(Decompiler.java:68)
         * com.taobao.arthas.core.command.klass100.JadCommand.processExactMatch(JadCommand.java:171)
         * com.taobao.arthas.core.command.klass100.JadCommand.process(JadCommand.java:147)
         * com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
         * com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
         * com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
         * com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
         * com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
         * java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
         * java.util.concurrent.FutureTask.run(FutureTask.java:266)
         * java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
         * java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
         * java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
         * java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
         * java.lang.Thread.run(Thread.java:748)
         */
        throw new IllegalStateException(Decompilation failed);
    }

ydq avatar Oct 14 '20 03:10 ydq

同样的问题, jad能反编译,但是watch和trace都报错Enhance error! exception: java.lang.NoClassDefFoundError: class names don't match

lp8608 avatar Jan 20 '21 04:01 lp8608

同样的问题, jad能反编译,但是watch和trace都报错Enhance error! exception: java.lang.NoClassDefFoundError: class names don't match

@lp8608 提交一个可重现的demo

hengyunabc avatar Jan 20 '21 06:01 hengyunabc

我也遇到了这个问题

[arthas@1]$ trace org.springframework.cloud.gateway.filter.GlobalFilter filter '#cost > 50' Affect(class count: 3 , method count: 3) cost in 1702 ms, listenerId: 1 Enhance error! exception: java.lang.ClassFormatError error happens when enhancing class: null, check arthas log: /root/logs/arthas/arthas.log

manzhizhen avatar Feb 25 '21 15:02 manzhizhen

我也遇到了这个问题

[arthas@1]$ trace org.springframework.cloud.gateway.filter.GlobalFilter filter '#cost > 50' Affect(class count: 3 , method count: 3) cost in 1702 ms, listenerId: 1 Enhance error! exception: java.lang.ClassFormatError error happens when enhancing class: null, check arthas log: /root/logs/arthas/arthas.log

https://github.com/alibaba/arthas/search?q=ClassFormatError&type=issues

hengyunabc avatar Feb 25 '21 15:02 hengyunabc

我也遇到了这个问题 [arthas@1]$ trace org.springframework.cloud.gateway.filter.GlobalFilter filter '#cost > 50' Affect(class count: 3 , method count: 3) cost in 1702 ms, listenerId: 1 Enhance error! exception: java.lang.ClassFormatError error happens when enhancing class: null, check arthas log: /root/logs/arthas/arthas.log

https://github.com/alibaba/arthas/search?q=ClassFormatError&type=issues

例子来了:

-- 报错信息

[arthas@1]$ trace org.springframework.cloud.gateway.filter.NettyRoutingFilter filter '#cost>50'
Affect(class count: 1 , method count: 1) cost in 29 ms, listenerId: 6
Enhance error! exception: java.lang.ClassFormatError
error happens when enhancing class: null, check arthas log: /root/logs/arthas/arthas.log

-- arthas.log 日志文件内容

2021-02-28 15:01:01 [arthas-command-execute] INFO  c.t.arthas.core.advisor.Enhancer -enhance matched classes: [class org.springframework.cloud.gateway.filter.NettyRoutingFilter]
2021-02-28 15:01:01 [arthas-command-execute] ERROR c.t.arthas.core.advisor.Enhancer -Enhancer error, matchingClasses: [class org.springframework.cloud.gateway.filter.NettyRoutingFilter]
java.lang.ClassFormatError: null
        at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
        at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
        at com.taobao.arthas.core.advisor.Enhancer.enhance(Enhancer.java:396)
        at com.taobao.arthas.core.command.monitor200.EnhancerCommand.enhance(EnhancerCommand.java:163)
        at com.taobao.arthas.core.command.monitor200.EnhancerCommand.process(EnhancerCommand.java:110)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
        at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

--被增强的类 Spring Cloud Gateway 2.1.2-RELEASE版本

package org.springframework.cloud.gateway.filter;

import java.net.URI;
import java.util.List;

import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.NettyPipeline;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClientResponse;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.config.HttpClientProperties;
import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter;
import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter.Type;
import org.springframework.cloud.gateway.support.TimeoutException;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.NettyDataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;

import static org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter.filterRequest;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_CONN_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_HEADER_NAMES;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.PRESERVE_HOST_HEADER_ATTRIBUTE;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.isAlreadyRouted;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setAlreadyRouted;

/**
 * @author Spencer Gibb
 * @author Biju Kunjummen
 */
public class NettyRoutingFilter implements GlobalFilter, Ordered {

	private static final Log log = LogFactory.getLog(NettyRoutingFilter.class);

	private final HttpClient httpClient;

	private final ObjectProvider<List<HttpHeadersFilter>> headersFiltersProvider;

	private final HttpClientProperties properties;

	// do not use this headersFilters directly, use getHeadersFilters() instead.
	private volatile List<HttpHeadersFilter> headersFilters;

	public NettyRoutingFilter(HttpClient httpClient,
			ObjectProvider<List<HttpHeadersFilter>> headersFiltersProvider,
			HttpClientProperties properties) {
		this.httpClient = httpClient;
		this.headersFiltersProvider = headersFiltersProvider;
		this.properties = properties;
	}

	public List<HttpHeadersFilter> getHeadersFilters() {
		if (headersFilters == null) {
			headersFilters = headersFiltersProvider.getIfAvailable();
		}
		return headersFilters;
	}

	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE;
	}

	@Override
	@SuppressWarnings("Duplicates")
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

		String scheme = requestUrl.getScheme();
		if (isAlreadyRouted(exchange)
				|| (!"http".equals(scheme) && !"https".equals(scheme))) {
			return chain.filter(exchange);
		}
		setAlreadyRouted(exchange);

		ServerHttpRequest request = exchange.getRequest();

		final HttpMethod method = HttpMethod.valueOf(request.getMethodValue());
		final String url = requestUrl.toString();

		HttpHeaders filtered = filterRequest(getHeadersFilters(), exchange);

		final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders();
		filtered.forEach(httpHeaders::set);

		String transferEncoding = request.getHeaders()
				.getFirst(HttpHeaders.TRANSFER_ENCODING);
		boolean chunkedTransfer = "chunked".equalsIgnoreCase(transferEncoding);

		boolean preserveHost = exchange
				.getAttributeOrDefault(PRESERVE_HOST_HEADER_ATTRIBUTE, false);

		Flux<HttpClientResponse> responseFlux = this.httpClient
				.chunkedTransfer(chunkedTransfer).request(method).uri(url)
				.send((req, nettyOutbound) -> {
					req.headers(httpHeaders);

					if (preserveHost) {
						String host = request.getHeaders().getFirst(HttpHeaders.HOST);
						req.header(HttpHeaders.HOST, host);
					}
					if (log.isTraceEnabled()) {
						nettyOutbound
								.withConnection(connection -> log.trace("outbound route: "
										+ connection.channel().id().asShortText()
										+ ", inbound: " + exchange.getLogPrefix()));
					}
					return nettyOutbound.options(NettyPipeline.SendOptions::flushOnEach)
							.send(request.getBody()
									.map(dataBuffer -> ((NettyDataBuffer) dataBuffer)
											.getNativeBuffer()));
				}).responseConnection((res, connection) -> {

					// Defer committing the response until all route filters have run
					// Put client response as ServerWebExchange attribute and write
					// response later NettyWriteResponseFilter
					exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
					exchange.getAttributes().put(CLIENT_RESPONSE_CONN_ATTR, connection);

					ServerHttpResponse response = exchange.getResponse();
					// put headers and status so filters can modify the response
					HttpHeaders headers = new HttpHeaders();

					res.responseHeaders().forEach(
							entry -> headers.add(entry.getKey(), entry.getValue()));

					String contentTypeValue = headers.getFirst(HttpHeaders.CONTENT_TYPE);
					if (StringUtils.hasLength(contentTypeValue)) {
						exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR,
								contentTypeValue);
					}

					HttpStatus status = HttpStatus.resolve(res.status().code());
					if (status != null) {
						response.setStatusCode(status);
					}
					else if (response instanceof AbstractServerHttpResponse) {
						// https://jira.spring.io/browse/SPR-16748
						((AbstractServerHttpResponse) response)
								.setStatusCodeValue(res.status().code());
					}
					else {
						// TODO: log warning here, not throw error?
						throw new IllegalStateException(
								"Unable to set status code on response: "
										+ res.status().code() + ", "
										+ response.getClass());
					}

					// make sure headers filters run after setting status so it is
					// available in response
					HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(
							getHeadersFilters(), headers, exchange, Type.RESPONSE);

					if (!filteredResponseHeaders
							.containsKey(HttpHeaders.TRANSFER_ENCODING)
							&& filteredResponseHeaders
									.containsKey(HttpHeaders.CONTENT_LENGTH)) {
						// It is not valid to have both the transfer-encoding header and
						// the content-length header
						// remove the transfer-encoding header in the response if the
						// content-length header is presen
						response.getHeaders().remove(HttpHeaders.TRANSFER_ENCODING);
					}

					exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES,
							filteredResponseHeaders.keySet());

					response.getHeaders().putAll(filteredResponseHeaders);

					return Mono.just(res);
				});

		if (properties.getResponseTimeout() != null) {
			responseFlux = responseFlux.timeout(properties.getResponseTimeout(),
					Mono.error(new TimeoutException("Response took longer than timeout: "
							+ properties.getResponseTimeout())))
					.onErrorMap(TimeoutException.class,
							th -> new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT,
									th.getMessage(), th));
		}

		return responseFlux.then(chain.filter(exchange));
	}

} 

manzhizhen avatar Feb 28 '21 07:02 manzhizhen

@manzhizhen 检查下 arthas版本,我测试最新的 3.4.8没有问题:

image

hengyunabc avatar Mar 01 '21 06:03 hengyunabc

我遇到同样的问题, 是因为用jrebel启动的debug模式 就会出现这种 不支持watch , trace TT等命令, 用正常模式启动就可以, 不知道是不是不支持jrebel插件.

ShuChangCloud avatar Sep 09 '22 06:09 ShuChangCloud

我遇到同样的问题, 是因为用jrebel启动的debug模式 就会出现这种 不支持watch , trace TT等命令, 用正常模式启动就可以, 不知道是不是不支持jrebel插件.

是的,不使用jrebel即可绑定

Tommy-LXDAO avatar Nov 11 '22 05:11 Tommy-LXDAO

我遇到同样的问题, 是因为用jrebel启动的debug模式 就会出现这种 不支持watch , trace TT等命令, 用正常模式启动就可以, 不知道是不是不支持jrebel插件.

感谢, 果然是, 我把jrebel关了正常使用调试没有问题了。

Poceer avatar Apr 19 '24 06:04 Poceer