java.lang.NoClassDefFoundError: com/gc/monitor/exception/MonitorException
Caused by: java.lang.ClassNotFoundException: com.gc.monitor.exception.MonitorException
錯誤訊息 `NoClassDefFoundError` 而非單純 `ClassNotFoundException`,暗示類曾被載入但初始化失敗,或存在多個版本的同名類。
「好不可思議啊!!居然是包重名!!」
推測專案中存在兩個 `com.gc.monitor.exception.MonitorException` 類:
類載入器按委派模型載入,先載入的版本被快取,後續請求返回同一個 `Class` 物件。若兩版本不兼容 (欄位/方法簽名不同),實際執行時會出現 `NoClassDefFoundError` 或 `IncompatibleClassChangeError`。
<dependency>
<groupId>com.example</groupId>
<artifactId>conflicting-lib</artifactId>
<exclusions>
<exclusion>
<groupId>com.gc.monitor</groupId>
<artifactId>monitor-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<relocations>
<relocation>
<pattern>com.gc.monitor.exception</pattern>
<shadedPattern>shaded.com.gc.monitor.exception</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetBeanName" value="monitorScript"/> <!-- 使用 Bean 名稱而非 class,確保 Spring 管理生命週期 -->
<property name="targetMethod" value="execute"/>
<property name="concurrent" value="false"/>
</bean>
<bean id="monitorScript" class="com.gc.monitor.MonitorScript" scope="prototype"/> <!-- prototype 避免狀態汙染 -->
`NoClassDefFoundError` 配合「類確實存在」且「改變 catch 位置即正常」,極大機率為類路徑重複/版本衝突。善用 `mvn dependency:tree`、`javap -cp` 驗證類簽名,嚴格管理依賴版本。