=============================
https://velog.io/@kimsw3445/BEA-160228-AppMerge-Failed
https://www.baeldung.com/java-find-class-version
=============================
일단 원인으로는 배포하려는 WebApplication의 라이브러리가
현재 weblogic을 동작시키고 있는 JDK 버전과 충돌나서 발생하는 현상으로 보인다.
즉, 컴파일이 된 class 파일의 JDK 버전과 운영중인 WebLogic의 JDK 버전과
상충되기에 발생한 현상으로 보인다.
<Jun 20, 2024 3:35:20,418 PM KST> <Error> <J2EE> <BEA-160228>
<AppMerge failed to merge your application.
If you are running AppMerge on the command-line, merge again with the -verbose option for more details.
See the error message(s) below.>
weblogic.utils.compiler.ToolFailureException:
Apps tool failure: Check nested exception for details
at weblogic.application.compiler.FlowDriver.handleStateChangeException(FlowDriver.java:55)
at weblogic.application.compiler.FlowDriver.nextState(FlowDriver.java:38)
at weblogic.application.compiler.AppMerge.runBody(AppMerge.java:168)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walkRecursive(ControlTreeWalker.java:334)
at com.bea.netuix.nf.ControlTreeWalker.walk(ControlTreeWalker.java:130)
at com.bea.netuix.nf.Lifecycle.processLifecycles(Lifecycle.java:399)
at com.bea.netuix.nf.Lifecycle.processLifecycles(Lifecycle.java:361)
at com.bea.netuix.nf.Lifecycle.processLifecycles(Lifecycle.java:352)
...
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:420)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:360)
Caused by: java.lang.IllegalArgumentException
at com.bea.objectweb.asm.ClassReader.<init>(Unknown Source)
at com.bea.objectweb.asm.ClassReader.<init>(Unknown Source)
at weblogic.application.utils.annotation.ClassInfoImpl.<init>(ClassInfoImpl.java:85)
at weblogic.application.utils.annotation.ClassInfoImpl.<init>(ClassInfoImpl.java:79)
...
at weblogic.application.utils.AnnotationDetector.scan(AnnotationDetector.java:172)
... 116 more
라이브러리 체킹 관련해서는 javap -v ${CLASS_FILE} | grep major 를 검색하며 하나하나 찾아봐야 한다.
하나하나 다 보기 귀찮다면, 아래의 코드는 chatGPT의 질의를 하고 얻은 스크립트다
지금 테스트 해봤는데 sh 파일 하나 만들고 실행하였고, nohup.out 파일에 tail -f 걸면서 보는데 잘 쌓인다.
#!/bin/bash
# 결과를 저장할 파일 지정
output_file="nohup.out"
# 결과 파일 초기화
> "$output_file"
# 전체 경로에서 .class 파일을 찾아서 반복문 실행
find . -type f -name "*.class" | while read -r classfile; do
# javap -v 명령어를 실행하여 major 버전 추출
major_version=$(javap -v "$classfile" | grep 'major version')
# 결과 출력
echo "File: $classfile" >> "$output_file"
echo "$major_version" >> "$output_file"
echo "----------------------" >> "$output_file"
# CPU 사용량을 줄이기 위해 약간의 지연 추가
sleep 0.1
done
# for window server PowerShell
# 결과를 저장할 파일 지정
$outputFile = "nohup.out"
# 결과 파일 초기화
Out-File -FilePath $outputFile -Force
# 전체 경로에서 .class 파일을 재귀적으로 찾기
Get-ChildItem -Path . -Recurse -Filter *.class | ForEach-Object {
$classFile = $_.FullName
# javap -v 명령어를 실행하여 major 버전 추출
$majorVersion = javap -v $classFile | Select-String -Pattern 'major version'
# 결과 출력
"File: $classFile" | Out-File -FilePath $outputFile -Append
"$majorVersion" | Out-File -FilePath $outputFile -Append
"----------------------" | Out-File -FilePath $outputFile -Append
# CPU 사용량을 줄이기 위해 약간의 지연 추가
Start-Sleep -Milliseconds 100
}
#이 스크립트를 백그라운드에서 실행하고, 출력을 nohup.out에 저장하려면 다음 단계를 따르세요:
1#.스크립트를 파일로 저장하세요. 예를 들어 CheckMajorVersion.ps1로 저장합니다.
2#.PowerShell을 관리자 권한으로 실행합니다.
3#.스크립트가 저장된 디렉토리로 이동합니다:
cd C:\path\to\script
4#. Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File .\CheckMajorVersion.ps1" -NoNewWindow -RedirectStandardOutput "nohup.out" -RedirectStandardError "nohup.out"
그리고 배포를 관리 콘솔이 아니라 weblogic.Deployer를 통해서 배포를 시도할 때,
DEBUG 레벨로 로깅을 설정하면 생각보다 쉽게 원인을 찾을 수가 있다.
[app@test1 bin]$ . ./setDomainEnv.sh
#java weblogic.Deployer -adminurl <관리콘솔주소:PORT> -username <콘솔계정ID> -password <콘솔PWD> -deploy <APP경로> -name <APP이름> -nostage -targets <타겟_인스턴스> -verbose -debug
[app@test1 bin]$ java weblogic.Deployer -adminurl xxx.xxx.xx.xxx:7001 -username weblogic -password weblogic11! -deploy /libtest -name libtest -nostage -targets M1 -verbose -debug
[BasicOperation.execute():517] : Initiating deploy operation for app, libtest, on targets:
[BasicOperation.execute():519] : M1
Task 4 initiated: [Deployer:149026]deploy application libtest on M1.
dumping Exception stack
Task 4 failed: [Deployer:149026]deploy application libtest on M1.
Target state: deploy failed on Server M1
java.lang.UnsupportedClassVersionError:
com/example/HelloServlet has been compiled by a more recent version of the Java Runtime
(class file version 55.0),
this version of the Java Runtime only recognizes class file versions up to 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at weblogic.utils.classloaders.GenericClassLoader.defineClassInternal(GenericClassLoader.java:1113)
at weblogic.utils.classloaders.GenericClassLoader.defineClass(GenericClassLoader.java:1046)
at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:1038)
JDK1.8로 설치한 WAS에 JDK 11 버전의 class 파일이 있어서 생긴 문제라는 것을 바로 보여준다.
부록으로 class version에 대한 글을 보면 다음과 같다.
## .class Version in Java
| Java SE 18 | 62 | 003e |
| Java SE 17 | 61 | 003d |
| Java SE 16 | 60 | 003c |
| Java SE 15 | 59 | 003b |
| Java SE 14 | 58 | 003a |
| Java SE 13 | 57 | 0039 |
| Java SE 12 | 56 | 0038 |
| Java SE 11 | 55 | 0037 |
| Java SE 10 | 54 | 0036 |
| Java SE 9 | 53 | 0035 |
| Java SE 8 | 52 | 0034 |
| Java SE 7 | 51 | 0033 |
| Java SE 6 | 50 | 0032 |
| Java SE 5 | 49 | 0031 |
| JDK 1.4 | 48 | 0030 |
| JDK 1.3 | 47 | 002f |
| JDK 1.2 | 46 | 002e |
| JDK 1.1 | 45 | 002d |
아래 글은 위의 링크에서 퍼온 글이다.
=====
검색 및 시도
해당 내용을 검색하자 Weblogic 업그레이드시(JAVA6 -> JAVA8) 발생하는 경우, JPA 2.1 사용, lib classpath 등의 케이스가 존재하였다.
JPA2.1
weblogic 12.1.3은 기본적으로 JPA2.1 버전을 지원하지 않는다. 하지만 JPA2.1을 사용하는 어플리케이션을 위해 별도의 CLASSPATH를 지정해주어 해당 어플리케이션 배포를 가능하게 할 수 있다.
cd ${DOMAIN_HOME}/bin/
vi setDomainEnv.sh
PRE_CLASSPATH=${ORACLE_HOME}/oracle_common/modules/javax.persistence_2.1.jar:${ORACLE_HOME}/wlserver/modules/com.oracle.weblogic.jpa21support_1.0.0.0_2-1.jar
위 설정 후에도 해당 환경에서는 정상적으로 배포가 되지 않았다.
JDK release 변경
jdk1.8.0_201 -> jdk1.8.0_321
cd ${DOMAIN_HOME}/bin/
vi setDomainEnv.sh
JAVA_HOME=/usr/bin/jdk1.8.0_321
위와같이 설정 변경 후, weblogic을 재기동.
ps -ef|grep java
를 통해 해당 릴리즈 버전으로 정상 기동되었는지 확인하였다.
위 설정 후에도 해당 환경에서는 정상적으로 배포가 되지 않았다.
LIB 검사
application 내 lib속 class의 이상 유무를 검사하였다.
cd lib
# 해당 명령어를 통하여 현재 디렉토리 내부 모든 jar 파일 압축을 해제하였다.
# 해당 명령어를 실행하기 전, lib 디렉토리를 복사 후 실행하자.
for i in `find . -name '*.jar'`; do unzip -qo $i -d $i.delemete; done
# 해당 명령어를 통하여 모든 class 파일의 자바 컴파일 버전을 확인하였다.
find . -name '*.class' |xargs javap -verbose
위 명령어 수행결과, 일부 클래스의 major version이 53임을 확인했다.
- Java 1.2 uses major version 46
- Java 1.3 uses major version 47
- Java 1.4 uses major version 48
- Java 5 uses major version 49
- Java 6 uses major version 50
- Java 7 uses major version 51
- Java 8 uses major version 52
- Java 9 uses major version 53
해당 클래스가 포함된 라이브러리(솔루션)의 버전을 낮춘 후 배포하자 정상 작동됨을 확인 할 수 있었다.
'WAS > WebLogic' 카테고리의 다른 글
| weblogic Socket Timeout 관련하여 정리 (0) | 2024.07.10 |
|---|---|
| JDK 업그레이드 (0) | 2024.06.19 |
| java.lang.OutOfMemoryError에 관하여 - panic action (0) | 2024.06.11 |
| [WebLogic] 세션 복제 시점 (0) | 2024.05.31 |
| WebLogic 인스턴스가 원인 불명의 shutdown이 발생한다. (0) | 2024.05.31 |