compiler message file broken:
key=compiler.misc.msg.bug arguments=11.0.13, {1}, {2}, {3}, {4}, {5}, {6}, {7} java.lang.AssertionError: Incorrect number of arguments; expected 4, found 0 에러
에러 발생 코드
에러가 발생한 코드를 살펴보자면 아래와 같다. REST API 호출 시 발생하는 예외를 executeApi() 메서드를 통해 공통적으로 처리했다. 이 코드 중에서 ParameterizedTypeReference<>(){} 부분에서 에러가 발생했다.
@Slf4j
@RequiredArgsConstructor
@Service
public class AuthUserApiService {
private final RestTemplate authApiRestTemplate;
public AuthUserDto findByUserId(Long userId) {
String path = String.format(FIND_BY_USER_ID, userId);
ResponseEntity<ResponseWrapper<AuthUserDto>> result = executeApi(
() -> authApiRestTemplate.exchange(path, new ParameterizedTypeReference<>() {
})
);
ResponseWrapper<AuthUserDto> resultBody = result.getBody();
if (resultBody == null || !resultBody.isSuccess()) {
throw new UserException("result data is not success");
}
return resultBody.getData();
}
public void deleteUser(UserDeleteDto deleteDto) {
executeApi(
() -> authApiRestTemplate
.exchange(DELETE, deleteDto, new ParameterizedTypeReference<>() {
}, HttpMethod.POST)
);
}
private <T> T executeApi(Supplier<T> supplier) {
try {
return supplier.get();
} catch (HttpClientErrorException e) {
log.info("rest exception: {}", e.getMessage(), e);
throw new UserException(e.getMessage);
} catch (Exception e) {
log.error("rest exception: {}", e.getMessage(), e);
throw new UserException(e.getMessage());
}
}
}
문제 원인
익명클래스 생성 시 다이아몬드 오퍼레이터 '<>'를 사용한 경우, 타입 추론이 불가능한 문제였다.
이 에러에는 이상한 점이 하나 있었다. 위 코드는 로컬에서는 잘 실행되지만, GitLab MR에 적용한 CI 과정에서는 항상 빌드 실패가 일어났다. 구글링을 해보니, 해당 문제는 JDK 11 일부 버전에서 발생하는 문제이고, 마이너 버전을 올리면서 fix 되었으니 버전을 업그레이드 하라고 한다.
참고 글
- https://stackoverflow.com/questions/61743652/compiler-message-file-broken-key-compiler-misc-msg-bug-arguments
- https://stackoverflow.com/questions/54775253/jdk-11-0-2-compilation-fails-with-javac-npe-on-anonymous-parameterized-class-typ
- https://reiphiel.tistory.com/130
자바 버전부터 확인해보았더니 내 로컬에서는 11.0.16, CI 환경(에러가 난 환경)은 11.0.13이었다.
문제 해결 방법
1. jdk 버전을 올린다.
꼭 jdk 11보다 더 높은 버전으로 올리지 않아도 된다. 마이너 버전만 올려도 충분하므로, 버전 올리는게 부담되지는 않을 것이다.
헌데 글들을 읽다보면 업데이트 해야한다는 버전이 다 다르다. 사용하는 jdk의 종류에 따라서 해당 문제가 fix된 시점이 다른가? 정도로만 추측해본다. 내가 사용하고 있는 temurin은 11.0.18부터 해당 문제를 수정했다는 듯 하다. (https://github.com/adoptium/adoptium-support/issues/678 참고) 특이하게도 예외적으로 11.0.16 에서는 해당 문제가 발생하지 않는다고 하는데 내가 딱 그 버전을 사용하고 있었다.😅
2. 타입을 명시적으로 선언해준다.
익명 클래스와 <>를 함께 사용했던 구간에 타입을 명시적으로 선언해준다.
@Slf4j
@RequiredArgsConstructor
@Service
public class AuthUserApiService {
private final RestTemplate authApiRestTemplate;
public AuthUserDto findByUserId(Long userId) {
String path = String.format(FIND_BY_USER_ID, userId);
ResponseEntity<ResponseWrapper<AuthUserDto>> result = executeApi(
// 수정된 부분: new ParameterizedTypeReference<> -> new ParameterizedTypeReference<ResponseWrapper<AuthUserDto>>
() -> authApiRestTemplate.exchange(path, new ParameterizedTypeReference<ResponseWrapper<AuthUserDto>>() {
})
);
ResponseWrapper<AuthUserDto> resultBody = result.getBody();
if (resultBody == null || !resultBody.isSuccess()) {
throw new UserException("result data is not success");
}
return resultBody.getData();
}
public void deleteUser(UserDeleteDto deleteDto) {
executeApi(
() -> authApiRestTemplate
// 수정된 부분: new ParameterizedTypeReference<> -> new ParameterizedTypeReference<Void>
.exchange(DELETE, deleteDto, new ParameterizedTypeReference<Void>() {
}, HttpMethod.POST)
);
}
private <T> T executeApi(Supplier<T> supplier) {...}
}
'Develop > Java' 카테고리의 다른 글
[Mockito] Invalid use of argument matchers! 에러 (0) | 2023.09.27 |
---|---|
[Java] UnaryOperator란? (0) | 2023.06.26 |
[Java] replaceAll 대신 replace 사용하기 (2) | 2023.01.22 |
[Java] 동시성 이슈 해결하기 (1) (0) | 2022.12.09 |
[JPA] delete문이 N개가 발생한다고요?😱 (2) | 2022.11.13 |