diff --git a/common/src/main/java/org/tron/core/exception/TronError.java b/common/src/main/java/org/tron/core/exception/TronError.java index 9d11d249476..2ea07499e55 100644 --- a/common/src/main/java/org/tron/core/exception/TronError.java +++ b/common/src/main/java/org/tron/core/exception/TronError.java @@ -47,6 +47,7 @@ public enum ErrCode { LOG_LOAD(1), WITNESS_INIT(1), RATE_LIMITER_INIT(1), + JDK_VERSION(1), SOLID_NODE_INIT(0); private final int code; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a716997419e..27739ff432e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1,6 +1,7 @@ package org.tron.core.config.args; import static java.lang.System.exit; +import static org.fusesource.jansi.Ansi.ansi; import static org.tron.common.math.Maths.max; import static org.tron.common.math.Maths.min; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; @@ -45,6 +46,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.fusesource.jansi.AnsiConsole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.arch.Arch; @@ -374,7 +376,17 @@ private static Map getOptionGroup() { * set parameters. */ public static void setParam(final String[] args, final String confFileName) { - Arch.throwIfUnsupportedJavaVersion(); + try { + Arch.throwIfUnsupportedJavaVersion(); + } catch (UnsupportedOperationException e) { + AnsiConsole.systemInstall(); + // To avoid confusion caused by silent execution when using -h or -v flags, + // errors are explicitly logged to the console in this context. + // Console output is not required for errors in other scenarios. + System.out.println(ansi().fgRed().a(e.getMessage()).reset()); + AnsiConsole.systemUninstall(); + throw new TronError(e, TronError.ErrCode.JDK_VERSION); + } clearParam(); // reset all parameters to avoid the influence in test JCommander.newBuilder().addObject(PARAMETER).build().parse(args); if (PARAMETER.version) { diff --git a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java index 6976e73b013..5670a441bc6 100644 --- a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java +++ b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java @@ -24,6 +24,7 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; +import org.tron.common.arch.Arch; import org.tron.common.log.LogService; import org.tron.common.parameter.RateLimiterInitialization; import org.tron.common.utils.ReflectUtils; @@ -41,7 +42,7 @@ public class TronErrorTest { public TemporaryFolder temporaryFolder = new TemporaryFolder(); @After - public void clearMocks() { + public void clearMocks() { Mockito.clearAllCaches(); Args.clearParam(); } @@ -115,7 +116,7 @@ public void rateLimiterServletInitTest() { @Test public void shutdownBlockTimeInitTest() { - Map params = new HashMap<>(); + Map params = new HashMap<>(); params.put(Constant.NODE_SHUTDOWN_BLOCK_TIME, "0"); params.put("storage.db.directory", "database"); Config config = ConfigFactory.defaultOverrides().withFallback( @@ -123,4 +124,30 @@ public void shutdownBlockTimeInitTest() { TronError thrown = assertThrows(TronError.class, () -> Args.setParam(config)); assertEquals(TronError.ErrCode.AUTO_STOP_PARAMS, thrown.getErrCode()); } + + @Test + public void testThrowIfUnsupportedJavaVersion() { + runArchTest(true, false, true); + runArchTest(true, true, false); + runArchTest(false, false, false); + } + + private void runArchTest(boolean isX86, boolean isJava8, boolean expectThrow) { + try (MockedStatic mocked = mockStatic(Arch.class)) { + mocked.when(Arch::isX86).thenReturn(isX86); + mocked.when(Arch::isJava8).thenReturn(isJava8); + mocked.when(Arch::getOsArch).thenReturn("x86_64"); + mocked.when(Arch::javaSpecificationVersion).thenReturn("17"); + mocked.when(Arch::withAll).thenReturn(""); + mocked.when(Arch::throwIfUnsupportedJavaVersion).thenCallRealMethod(); + + if (expectThrow) { + assertEquals(TronError.ErrCode.JDK_VERSION, assertThrows( + TronError.class, () -> Args.setParam(new String[]{}, Constant.TEST_CONF)).getErrCode()); + } else { + Arch.throwIfUnsupportedJavaVersion(); + } + } + } + } diff --git a/platform/src/main/java/common/org/tron/common/arch/Arch.java b/platform/src/main/java/common/org/tron/common/arch/Arch.java index e9edf8945d4..e91c626ff66 100644 --- a/platform/src/main/java/common/org/tron/common/arch/Arch.java +++ b/platform/src/main/java/common/org/tron/common/arch/Arch.java @@ -73,8 +73,8 @@ public static void throwIfUnsupportedJavaVersion() { if (isX86() && !isJava8()) { logger.info(withAll()); throw new UnsupportedOperationException(String.format( - "Java %s is required for %s architecture. Detected version %s", - "1.8 ", getOsArch(), javaSpecificationVersion())); + "Java %s is required for %s architecture. Detected version %s", "1.8", + getOsArch(), javaSpecificationVersion())); } }