偶尔我的测试会被挂起(这发生在我们的构建服务器而不是本地)。使用jstack告诉我在等待套接字读取时测试被卡住了。这可能是我的单元测试或休息模板中使用wire mock?有没有人见过这个?
我的测试看起来像
@RunWith(MockitoJUnitRunner.class)
public class XxxServiceTest {
private static final int PORT = 10222;
private static final String HOST = "localhost:" + PORT;
private static final String PATH = "/1.0/api";
private static final String ACCOUNTS_PATH = PATH + "/user";
private static final String TWO_FACTOR_VALIDATE_PATH = "/validate/token";
private static final String QUESTION_MARK_WITH_ANY_PARAMETERS = "?.*";
private static final int HTTP_OK = 200;
private static final int HTTP_NOT_FOUND = 404;
private static final int HTTP_FORBIDDEN = 401;
private static final String ENCRYPTED_USER_ID = "?userId=";
private static final String UTF_8 = "UTF-8";
private static final String TWO_FACTOR_AUTH_CODE = "SOME_TwO_FACTOR_AUTH";
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification="JUnit rules must be public")
@Rule
public WireMockRule wireMockRule = new WireMockRule(PORT);
private XxxService testSubject;
@Before
public void createTestSubject() throws Exception {
final RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
testSubject = new XxxService(template, authorityGranter);
final String http = "http://";
set(XxxService.class, "restUrl").to(http + HOST + PATH).on(testSubject);
set(XxxService.class, "authUrl").to(http + HOST + TWO_FACTOR_VALIDATE_PATH).on(testSubject);
}
private PreAuthenticatedAuthenticationToken tokenWithPrinciple(final String principle) {
final AuthenticationDetails details = new AuthenticationDetails(Optional.of(principle), Optional.empty(), Optional.of(TWO_FACTOR_AUTH_CODE));
return new PreAuthenticatedAuthenticationToken(details, "");
}
private void respondsWithAccountDetails() throws IOException {
responseWithContentsOfFile("/somefilepath/XxxServiceTest.response.json");
}
private void responseWithContentsOfFile(final String filename) throws IOException {
final String json = IOUtils.toString(getClass().getResourceAsStream(filename));
stubFor(get(urlMatching(ACCOUNTS_PATH + QUESTION_MARK_WITH_ANY_PARAMETERS))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(HTTP_OK)
.withBody(json)));
}
private void failsTwoFactorAuth() {
stubFor(get(urlEqualTo(TWO_FACTOR_VALIDATE_PATH)).willReturn(aResponse().withStatus(HTTP_FORBIDDEN)));
}
@Test(expected = TwoFactorAuthenticationException.class)
public void failsAuthenticationWhenTwoFactorCodeIsIncorrect() throws Exception{
// Given
respondsWithAccountDetails();
failsTwoFactorAuth();
// When
testSubject.loadUserDetails(tokenWithPrinciple("PrincipleTokenWithoutValidTwoFactor"));
}
}
生产代码如下:
public class XxxService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
private static final Log LOGGER = LogFactory.getLog(UrsService.class);
@Value("${services.user.restUrl}")
private String restUrl;
@Value("${services.user.authUrl}")
private String authUrl;
private final RestTemplate rest;
@Override
public UserDetails loadUserDetails(final PreAuthenticatedAuthenticationToken token) {
final AuthenticationDetails principalToken = (AuthenticationDetails) token.getPrincipal();
validateTwoFactorToken(principalToken.getTwoFactorAuthCode());
try {
return getUserDetails(principalToken);
} catch (HttpServerErrorException|HttpClientErrorException e) {
throw new UsernameNotFoundException("Failed to fetch user details.", e);
}
}
private void validateToken(final String twoFactorAuthCode) {
validateTwoFactorToken(twoFactorAuthCode);
}
private void validateTwoFactorToken(final String twoFactorAuthCode) {
try {
final HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + twoFactorAuthCode);
headers.setContentType(MediaType.APPLICATION_JSON);
final HttpEntity<String> entity = new HttpEntity<String>("twoFactor", headers);
final ResponseEntity<String> validation = rest.exchange(authUrl, HttpMethod.GET, entity, String.class);
} catch (HttpServerErrorException |HttpClientErrorException e) {
throw new TwoFactorAuthenticationException(twoFactorAuthCode, e);
}
}
private UserDetails getUserDetails(final AuthenticationDetails principalToken) {
final HttpEntity<String> entity = new HttpEntity<String>("parameters", restHeaders());
final ResponseEntity<User[]> exchange = rest.exchange(restUrl, HttpMethod.GET, entity, User[].class, principalToken.getEncryptedUserId().get());
return UserDetails.from(exchange.getBody(), authorityGranter);
}
}
jstack的完整输出是:
Attaching to process ID 11243, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.31-b07
Deadlock Detection:
No deadlocks found.
Thread 11431: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- org.mortbay.thread.QueuedThreadPool$PoolThread.run() @bci=421, line=626 (Interpreted frame)
Thread 11430: (state = IN_NATIVE)
- java.net.PlainSocketImpl.socketAccept(java.net.SocketImpl) @bci=0 (Interpreted frame)
- java.net.AbstractPlainSocketImpl.accept(java.net.SocketImpl) @bci=7, line=404 (Interpreted frame)
- java.net.ServerSocket.implAccept(java.net.Socket) @bci=60, line=545 (Interpreted frame)
- java.net.ServerSocket.accept() @bci=48, line=513 (Interpreted frame)
- com.github.tomakehurst.wiremock.jetty6.DelayableSocketConnector.accept(int) @bci=8, line=34 (Interpreted frame)
- org.mortbay.jetty.AbstractConnector$Acceptor.run() @bci=212, line=708 (Interpreted frame)
- org.mortbay.thread.QueuedThreadPool$PoolThread.run() @bci=42, line=582 (Interpreted frame)
Thread 11372: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.ref.ReferenceQueue.remove(long) @bci=44, line=142 (Compiled frame)
- java.lang.ref.ReferenceQueue.remove() @bci=2, line=158 (Compiled frame)
- sun.java2d.Disposer.run() @bci=3, line=148 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
Thread 11287: (state = IN_NATIVE)
- sun.nio.ch.EPollArrayWrapper.epollWait(long, int, long, int) @bci=0 (Interpreted frame)
- sun.nio.ch.EPollArrayWrapper.poll(long) @bci=18, line=269 (Interpreted frame)
- sun.nio.ch.EPollSelectorImpl.doSelect(long) @bci=28, line=79 (Interpreted frame)
- sun.nio.ch.SelectorImpl.lockAndDoSelect(long) @bci=37, line=86 (Interpreted frame)
- sun.nio.ch.SelectorImpl.select(long) @bci=30, line=97 (Interpreted frame)
- sun.nio.ch.SelectorImpl.select() @bci=2, line=101 (Interpreted frame)
- org.gradle.messaging.remote.internal.inet.SocketConnection$SocketInputStream.read(byte[], int, int) @bci=43, line=154 (Interpreted frame)
- com.esotericsoftware.kryo.io.Input.fill(byte[], int, int) @bci=36, line=139 (Interpreted frame)
- com.esotericsoftware.kryo.io.Input.require(int) @bci=130, line=159 (Interpreted frame)
- com.esotericsoftware.kryo.io.Input.readByte() @bci=6, line=255 (Interpreted frame)
- org.gradle.internal.serialize.kryo.KryoBackedDecoder.readByte() @bci=8, line=80 (Interpreted frame)
- org.gradle.messaging.remote.internal.hub.InterHubMessageSerializer$MessageReader.read() @bci=8, line=63 (Interpreted frame)
- org.gradle.messaging.remote.internal.hub.InterHubMessageSerializer$MessageReader.read() @bci=5, line=52 (Interpreted frame)
- org.gradle.messaging.remote.internal.inet.SocketConnection.receive() @bci=8, line=77 (Interpreted frame)
- org.gradle.messaging.remote.internal.hub.MessageHub$ConnectionReceive.run() @bci=8, line=235 (Interpreted frame)
- org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(java.lang.Runnable) @bci=5, line=54 (Interpreted frame)
- org.gradle.internal.concurrent.StoppableExecutorImpl$1.run() @bci=33, line=40 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1142 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=617 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
Thread 11286: (state = BLOCKED)
- sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
- java.util.concurrent.locks.LockSupport.park(java.lang.Object) @bci=14, line=175 (Compiled frame)
- java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await() @bci=42, line=2039 (Compiled frame)
- org.gradle.messaging.remote.internal.hub.queue.EndPointQueue.take(java.util.Collection) @bci=55, line=49 (Compiled frame)
- org.gradle.messaging.remote.internal.hub.MessageHub$ConnectionDispatch.run() @bci=37, line=278 (Interpreted frame)
- org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(java.lang.Runnable) @bci=5, line=54 (Interpreted frame)
- org.gradle.internal.concurrent.StoppableExecutorImpl$1.run() @bci=33, line=40 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1142 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=617 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
Thread 11285: (state = IN_NATIVE)
- java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Compiled frame; information may be imprecise)
- java.net.SocketInputStream.read(byte[], int, int, int) @bci=79, line=150 (Compiled frame)
- java.net.SocketInputStream.read(byte[], int, int) @bci=11, line=121 (Compiled frame)
- java.io.BufferedInputStream.fill() @bci=214, line=246 (Interpreted frame)
- java.io.BufferedInputStream.read1(byte[], int, int) @bci=44, line=286 (Interpreted frame)
- java.io.BufferedInputStream.read(byte[], int, int) @bci=49, line=345 (Interpreted frame)
- sun.net.www.http.HttpClient.parseHTTPHeader(sun.net.www.MessageHeader, sun.net.ProgressSource, sun.net.www.protocol.http.HttpURLConnection) @bci=51, line=703 (Interpreted frame)
- sun.net.www.http.HttpClient.parseHTTP(sun.net.www.MessageHeader, sun.net.ProgressSource, sun.net.www.protocol.http.HttpURLConnection) @bci=56, line=647 (Interpreted frame)
- sun.net.www.protocol.http.HttpURLConnection.getInputStream0() @bci=327, line=1535 (Compiled frame)
- sun.net.www.protocol.http.HttpURLConnection.getInputStream() @bci=52, line=1440 (Compiled frame)
- java.net.HttpURLConnection.getResponseCode() @bci=16, line=480 (Interpreted frame)
- org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode() @bci=8, line=48 (Interpreted frame)
- org.springframework.http.client.AbstractClientHttpResponse.getStatusCode() @bci=5, line=33 (Interpreted frame)
- org.springframework.web.client.DefaultResponseErrorHandler.getHttpStatusCode(org.springframework.http.client.ClientHttpResponse) @bci=5, line=56 (Interpreted frame)
- org.springframework.web.client.DefaultResponseErrorHandler.hasError(org.springframework.http.client.ClientHttpResponse) @bci=7, line=50 (Interpreted frame)
- org.springframework.web.client.RestTemplate.handleResponse(java.net.URI, org.springframework.http.HttpMethod, org.springframework.http.client.ClientHttpResponse) @bci=14, line=629 (Interpreted frame)
- org.springframework.web.client.RestTemplate.doExecute(java.net.URI, org.springframework.http.HttpMethod, org.springframework.web.client.RequestCallback, org.springframework.web.client.ResponseExtractor) @bci=75, line=597 (Interpreted frame)
- org.springframework.web.client.RestTemplate.execute(java.lang.String, org.springframework.http.HttpMethod, org.springframework.web.client.RequestCallback, org.springframework.web.client.ResponseExtractor, java.lang.Object[]) @bci=26, line=557 (Interpreted frame)
- org.springframework.web.client.RestTemplate.exchange(java.lang.String, org.springframework.http.HttpMethod, org.springframework.http.HttpEntity, java.lang.Class, java.lang.Object[]) @bci=31, line=475 (Interpreted frame)
- xxx.xxx.XxxService.validateTwoFactorToken(java.lang.String) @bci=75, line=82 (Interpreted frame)
- xxx.xxx.XxxService.validateToken(merlin.web.traderportal.app.security.AuthenticationDetails) @bci=63, line=72 (Interpreted frame)
- xxx.xxx.XxxService.loadUserDetails(org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken) @bci=14, line=54 (Interpreted frame)
- xxx.xxx.XxxServiceTest.failsAuthenticationWhenTwoFactorCodeIsIncorrect() @bci=22, line=255 (Interpreted frame)
- sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) @bci=0 (Compiled frame)
- sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=100, line=62 (Compiled frame)
- sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=43 (Compiled frame)
- java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=56, line=483 (Compiled frame)
- org.junit.runners.model.FrameworkMethod$1.runReflectiveCall() @bci=19, line=47 (Interpreted frame)
- org.junit.internal.runners.model.ReflectiveCallable.run() @bci=5, line=12 (Interpreted frame)
- org.junit.runners.model.FrameworkMethod.invokeExplosively(java.lang.Object, java.lang.Object[]) @bci=14, line=44 (Interpreted frame)
- org.junit.internal.runners.statements.InvokeMethod.evaluate() @bci=16, line=17 (Interpreted frame)
- org.junit.internal.runners.statements.ExpectException.evaluate() @bci=14, line=19 (Interpreted frame)
- org.junit.internal.runners.statements.RunBefores.evaluate() @bci=61, line=26 (Interpreted frame)
- com.github.tomakehurst.wiremock.junit.WireMockRule$1.evaluate() @bci=38, line=62 (Interpreted frame)
- org.junit.rules.RunRules.evaluate() @bci=8, line=20 (Interpreted frame)
- org.junit.runners.ParentRunner.runLeaf(org.junit.runners.model.Statement, org.junit.runner.Description, org.junit.runner.notification.RunNotifier) @bci=28, line=271 (Interpreted frame)
- org.junit.runners.BlockJUnit4ClassRunner.runChild(org.junit.runners.model.FrameworkMethod, org.junit.runner.notification.RunNotifier) @bci=42, line=70 (Interpreted frame)
- org.junit.runners.BlockJUnit4ClassRunner.runChild(java.lang.Object, org.junit.runner.notification.RunNotifier) @bci=10, line=50 (Interpreted frame)
- org.junit.runners.ParentRunner$3.run() @bci=16, line=238 (Interpreted frame)
- org.junit.runners.ParentRunner$1.schedule(java.lang.Runnable) @bci=5, line=63 (Interpreted frame)
- org.junit.runners.ParentRunner.runChildren(org.junit.runner.notification.RunNotifier) @bci=51, line=236 (Interpreted frame)
- org.junit.runners.ParentRunner.access$000(org.junit.runners.ParentRunner, org.junit.runner.notification.RunNotifier) @bci=6, line=53 (Interpreted frame)
- org.junit.runners.ParentRunner$2.evaluate() @bci=12, line=229 (Interpreted frame)
- org.junit.runners.ParentRunner.run(org.junit.runner.notification.RunNotifier) @bci=31, line=309 (Interpreted frame)
- org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(org.junit.runner.notification.RunNotifier) @bci=21, line=37 (Interpreted frame)
- org.mockito.runners.MockitoJUnitRunner.run(org.junit.runner.notification.RunNotifier) @bci=9, line=62 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(java.lang.String) @bci=297, line=105 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(java.lang.String) @bci=22, line=56 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(org.gradle.api.internal.tasks.testing.TestClassRunInfo) @bci=30, line=64 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(org.gradle.api.internal.tasks.testing.TestClassRunInfo) @bci=9, line=50 (Interpreted frame)
- sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) @bci=0 (Compiled frame)
- sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=100, line=62 (Compiled frame)
- sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=43 (Compiled frame)
- java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=56, line=483 (Compiled frame)
- org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(org.gradle.messaging.dispatch.MethodInvocation) @bci=23, line=35 (Interpreted frame)
- org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(java.lang.Object) @bci=9, line=24 (Interpreted frame)
- org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(java.lang.Object) @bci=30, line=32 (Interpreted frame)
- org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) @bci=246, line=93 (Compiled frame)
- com.sun.proxy.$Proxy2.processTestClass(org.gradle.api.internal.tasks.testing.TestClassRunInfo) @bci=20 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(org.gradle.api.internal.tasks.testing.TestClassRunInfo) @bci=22, line=106 (Interpreted frame)
- sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) @bci=0 (Compiled frame)
- sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=100, line=62 (Compiled frame)
- sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=43 (Compiled frame)
- java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=56, line=483 (Compiled frame)
- org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(org.gradle.messaging.dispatch.MethodInvocation) @bci=23, line=35 (Interpreted frame)
- org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(java.lang.Object) @bci=9, line=24 (Interpreted frame)
- org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run() @bci=211, line=360 (Interpreted frame)
- org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(java.lang.Runnable) @bci=5, line=54 (Interpreted frame)
- org.gradle.internal.concurrent.StoppableExecutorImpl$1.run() @bci=33, line=40 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1142 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=617 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
Thread 11265: (state = BLOCKED)
Thread 11264: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.ref.ReferenceQueue.remove(long) @bci=44, line=142 (Compiled frame)
- java.lang.ref.ReferenceQueue.remove() @bci=2, line=158 (Compiled frame)
- java.lang.ref.Finalizer$FinalizerThread.run() @bci=36, line=209 (Interpreted frame)
Thread 11263: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.Object.wait() @bci=2, line=502 (Interpreted frame)
- java.lang.ref.Reference$ReferenceHandler.run() @bci=36, line=157 (Interpreted frame)
Thread 11259: (state = BLOCKED)
- sun.misc.Unsafe.park(boolean, long) @bci=0 (Interpreted frame)
- java.util.concurrent.locks.LockSupport.park(java.lang.Object) @bci=14, line=175 (Interpreted frame)
- java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt() @bci=1, line=836 (Interpreted frame)
- java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(int) @bci=72, line=997 (Interpreted frame)
- java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(int) @bci=24, line=1304 (Interpreted frame)
- java.util.concurrent.CountDownLatch.await() @bci=5, line=231 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(org.gradle.process.internal.WorkerProcessContext) @bci=70, line=69 (Interpreted frame)
- org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(java.lang.Object) @bci=9, line=45 (Interpreted frame)
- org.gradle.process.internal.child.ActionExecutionWorker.execute(org.gradle.process.internal.child.WorkerContext) @bci=110, line=85 (Interpreted frame)
- org.gradle.process.internal.child.ActionExecutionWorker.execute(java.lang.Object) @bci=9, line=37 (Interpreted frame)
- org.gradle.process.internal.child.ImplementationClassLoaderWorker.execute(org.gradle.process.internal.child.WorkerContext) @bci=219, line=87 (Interpreted frame)
- org.gradle.process.internal.child.ImplementationClassLoaderWorker.execute(java.lang.Object) @bci=9, line=41 (Interpreted frame)
- org.gradle.process.internal.child.SystemApplicationClassLoaderWorker.call() @bci=41, line=49 (Interpreted frame)
- org.gradle.process.internal.child.SystemApplicationClassLoaderWorker.call() @bci=5, line=33 (Interpreted frame)
- jarjar.org.gradle.process.internal.launcher.GradleWorkerMain.run() @bci=313, line=69 (Interpreted frame)
- jarjar.org.gradle.process.internal.launcher.GradleWorkerMain.main(java.lang.String[]) @bci=11, line=74 (Interpreted frame)