opengoofy / hippo4j

📌 异步线程池框架,支持线程池动态变更&监控&报警,无需修改代码轻松引入。Asynchronous thread pool framework, support Thread Pool Dynamic Change & monitoring & Alarm, no need to modify the code easily introduced.
https://hippo4j.cn
Apache License 2.0
5.47k stars 1.16k forks source link

[Bug] Start client side log printing, reflection error, resulting in thread pool failure #1368

Open Jamel-jun opened 1 year ago

Jamel-jun commented 1 year ago

问题必现

BUG日志:客户端应用启动时打印如下日志

image

目前解决方案

启动jar时加上vm参数:--add-opens java.base/java.util.concurrent=ALL-UNNAMED

iwangjie commented 1 year ago

Java9 broke reflection and as the version number goes up, the breaks get worse. Essentially, accessing non-exported elements of other modules (modules introduced in java 9) does not work without adding a bevy of complicated lines when starting the java executable. "modules" as a concept did not exist prior to java9, hence, the java8 and below javadoc makes no mention of any of this.--add-opens.

see: https://stackoverflow.com/questions/74723932/java-17-reflection-issue

Jamel-jun commented 1 year ago

Java9 broke reflection and as the version number goes up, the breaks get worse. Essentially, accessing non-exported elements of other modules (modules introduced in java 9) does not work without adding a bevy of complicated lines when starting the java executable. "modules" as a concept did not exist prior to java9, hence, the java8 and below javadoc makes no mention of any of this.--add-opens.

see: https://stackoverflow.com/questions/74723932/java-17-reflection-issue

I have solved the problem through -- add-opens. Should I use other implementation solutions to be compatible with jdk17 and avoid reflection?

iwangjie commented 1 year ago

Java9 broke reflection and as the version number goes up, the breaks get worse. Essentially, accessing non-exported elements of other modules (modules introduced in java 9) does not work without adding a bevy of complicated lines when starting the java executable. "modules" as a concept did not exist prior to java9, hence, the java8 and below javadoc makes no mention of any of this.--add-opens. see: https://stackoverflow.com/questions/74723932/java-17-reflection-issue

I have solved the problem through -- add-opens. Should I use other implementation solutions to be compatible with jdk17 and avoid reflection?

Unfortunately, there is no better solution, and as the article states, the compatibility issues associated with upgrading the JDK may persist for a long time to be resolved.

iwangjie commented 1 year ago

Java9 broke reflection and as the version number goes up, the breaks get worse. Essentially, accessing non-exported elements of other modules (modules introduced in java 9) does not work without adding a bevy of complicated lines when starting the java executable. "modules" as a concept did not exist prior to java9, hence, the java8 and below javadoc makes no mention of any of this.--add-opens. see: https://stackoverflow.com/questions/74723932/java-17-reflection-issue

I have solved the problem through -- add-opens. Should I use other implementation solutions to be compatible with jdk17 and avoid reflection?

Unfortunately, there is no better solution, and as the article states, the compatibility issues associated with upgrading the JDK may persist for a long time to be resolved.

fuxiuzhan commented 1 year ago

高版本jdk对反射修改做了限制,不过可以使用unsafe修改,juc里大量使用unsafe,所以unsafe就变得相对safe了。see this:https://github.com/fuxiuzhan/fuled-component/blob/master/fuled-dynamic-threadpool-starter/src/main/java/com/fxz/fuled/dynamic/threadpool/ThreadPoolRegistry.java

fuxiuzhan commented 1 year ago

/**

如下直接生成新的queue替换原有的引用,如果原始的queue里已经有堆积的任务,直接替换是不是会丢任务?

BlockingQueue workQueue = BlockingQueueTypeEnum.createBlockingQueue(threadPoolParameterInfo.getQueueType(), threadPoolParameterInfo.getCapacity()); ReflectUtil.setFieldValue(executor, "workQueue", workQueue); // fix https://github.com/opengoofy/hippo4j/issues/1063 ThreadPoolExecutorUtil.safeSetPoolSize(executor, threadPoolParameterInfo.corePoolSizeAdapt(), threadPoolParameterInfo.maximumPoolSizeAdapt()); executor.setKeepAliveTime(threadPoolParameterInfo.getKeepAliveTime(), TimeUnit.SECONDS); executor.allowCoreThreadTimeOut(EnableEnum.getBool(threadPoolParameterInfo.getAllowCoreThreadTimeOut())); executor.setRejectedExecutionHandler(RejectedPolicyTypeEnum.createPolicy(threadPoolParameterInfo.getRejectedType())); if (executor instanceof DynamicThreadPoolExecutor) { Optional.ofNullable(threadPoolParameterInfo.getExecuteTimeOut()) .ifPresent(executeTimeOut -> ((DynamicThreadPoolExecutor) executor).setExecuteTimeOut(executeTimeOut)); } }

Createsequence commented 1 year ago

/* Thread-pool param replace. @param executor dynamic thread-pool executor @param threadPoolParameterInfo thread-pool parameter info / private void threadPoolParamReplace(ThreadPoolExecutor executor, ThreadPoolParameterInfo threadPoolParameterInfo) {

如下直接生成新的queue替换原有的引用,如果原始的queue里已经有堆积的任务,直接替换是不是会丢任务?

BlockingQueue workQueue = BlockingQueueTypeEnum.createBlockingQueue(threadPoolParameterInfo.getQueueType(), threadPoolParameterInfo.getCapacity()); ReflectUtil.setFieldValue(executor, "workQueue", workQueue); // fix #1063 ThreadPoolExecutorUtil.safeSetPoolSize(executor, threadPoolParameterInfo.corePoolSizeAdapt(), threadPoolParameterInfo.maximumPoolSizeAdapt()); executor.setKeepAliveTime(threadPoolParameterInfo.getKeepAliveTime(), TimeUnit.SECONDS); executor.allowCoreThreadTimeOut(EnableEnum.getBool(threadPoolParameterInfo.getAllowCoreThreadTimeOut())); executor.setRejectedExecutionHandler(RejectedPolicyTypeEnum.createPolicy(threadPoolParameterInfo.getRejectedType())); if (executor instanceof DynamicThreadPoolExecutor) { Optional.ofNullable(threadPoolParameterInfo.getExecuteTimeOut()) .ifPresent(executeTimeOut -> ((DynamicThreadPoolExecutor) executor).setExecuteTimeOut(executeTimeOut)); } }

We may need to verify that this problem exists. If it does, we may need to add extra steps here to ensure that tasks in the old queue are not lost when the work queue is replaced:

If you don't mind, you can try to verify this problem first :)