【冷知识】模块命名,util、tool还是service

本文探讨了软件开发中工具类、帮助类和服务类的区别,包括util、tool、service及helper等不同命名方式的应用场景,并提供了实用建议。
该文章已生成可运行项目,

软件开发中总少不了各种工具类,除了引入一些第三方的库之外,还会根据自己的工程特点、业务特性写一些帮助类。比如封装的时间处理方法、文件处理方法、协议解析方法等等。
由于软件开发是用英文的人发明的,虽然某些语言(比如java)也能用中文命名(但是正式开发中这么干的估计都被谈过话了),总归还是用英文字符的命名模块名、类名的。
出于中英文互译的模糊性,util、tool都有工具的意思,什么时候该用哪个,虽然没有个类似jep、w3c的标准约束着你,单总归还是要自己心里有数才是。经过简单搜索,得出
util是通用业务无关可供其他程序使用的,可以用在其他系统中使用,类似apache commons这类,比如开发了个DateUtil,任何一个同语言、无兼容性问题的工程都可以引用一下。
tool是通用的部分业务相关的,因此不能用在其他系统体系中,比如校验用户身份信息的UserTool,可在资源处理、需要鉴权的部分使用,但在其他系统中不能直接移植。
service是处理单一业务的,UserService就只处理用户的相关操作。


另:
Helper,也叫帮助类的意思,但是用Helper命名的一般是一些功能辅助,SqlHelper封装数据库连接操作提供数据库操作对象,ConfigHelper帮助创建配置信息用于模块初始化构建。

其他的搜到有机会再补充。
参考:Java 包与类的命名(util、service、tool)区别

本文章已经生成可运行项目
java.lang.IllegalAccessError: superclass access check failed: class org.jetbrains.kotlin.kapt3.base.javac.KaptJavaCompiler (in unnamed module @0x78932a5e) cannot access class com.sun.tools.javac.main.JavaCompiler (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.main to unnamed module @0x78932a5e at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(Unknown Source) at java.base/java.security.SecureClassLoader.defineClass(Unknown Source) at java.base/java.net.URLClassLoader.defineClass(Unknown Source) at java.base/java.net.URLClassLoader$1.run(Unknown Source) at java.base/java.net.URLClassLoader$1.run(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at java.base/java.net.URLClassLoader.findClass(Unknown Source) at java.base/java.lang.ClassLoader.loadClass(Unknown Source) at java.base/java.lang.ClassLoader.loadClass(Unknown Source) at org.jetbrains.kotlin.kapt3.base.KaptContext.<init>(KaptContext.kt:55) at org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration.<init>(KaptContextForStubGeneration.kt:38) at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:295) at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:174) at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:104) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:104) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:88) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:256) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:42) at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:115) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:247) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:87) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:47) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:168) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:100) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:46) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:460) at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:62) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:476) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:399) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:280) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:124) at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:636) at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:101) at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1598) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Errors were stored into D:\DevelopmentTool\AndroidProject\PlatformWeight\.gradle\kotlin\errors\errors-1758934981852.log
最新发布
09-28
<think>我们正在解决一个关于Java模块访问权限的问题,具体错误是: java.lang.IllegalAccessError: superclass access check failed: class org.jetbrains.kotlin.kapt3.base.javac.KaptJavaCompiler (in unnamed module @0x4a9acb91) cannot access class com.sun.tools.javac.main.JavaCompiler (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.main to unnamed module @0x4a9acb91 这个错误发生在使用Kotlin kapt(注解处理工具)时,因为从Java 9开始引入的模块系统限制了内部API的访问。kapt需要访问JDK内部的`com.sun.tools.javac`包中的类,但是默认情况下这些包没有导出给未命名模块(即我们的应用程序)。 根据引用[^1]中的错误信息,我们可以看到类似的错误(无法访问`com.sun.tools.javac.util.Context`),这表明我们需要将`jdk.compiler`模块中的几个包导出给未命名模块。 ### 解决方案步骤 #### 方法1: 通过JVM参数导出包(推荐) 我们可以通过添加JVM参数来显式地导出所需的包。具体来说,我们需要导出以下包(根据错误信息中缺失的访问): - `com.sun.tools.javac.main` - `com.sun.tools.javac.util`(引用[^1]中提到了这个包) - 可能还需要其他包,如`com.sun.tools.javac.api`,`com.sun.tools.javac.file`,`com.sun.tools.javac.processing`等,因为kapt使用到了这些内部API。 **在Gradle项目中配置:** 1. 在项目根目录的`gradle.properties`文件中添加以下JVM参数: ```properties org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED ``` 2. 如果上述方法不起作用,或者你希望在特定任务中添加参数(比如kapt任务),可以在`build.gradle`文件中为kapt任务单独配置: ```groovy tasks.withType(org.jetbrains.kotlin.gradle.tasks.KaptTask).configureEach { jvmArgs += [ '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED' ] } ``` **在Maven项目中配置:** 在`pom.xml`中配置`kotlin-maven-plugin`插件,添加`<arg>`元素: ```xml <build> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions>...</executions> <configuration> <args> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg> </args> </configuration> </plugin> </plugins> </build> ``` #### 方法2: 升级Kotlin版本 Kotlin的新版本通常会修复与新版JDK的兼容性问题。请确保你使用的Kotlin版本至少为1.5.0或更高(推荐使用最新稳定版,如1.9.0+)。 在Gradle中升级Kotlin版本: ```gradle buildscript { ext.kotlin_version = '1.9.0' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } ``` #### 方法3: 降级JDK版本 如果上述方法都不能解决问题,或者你暂时不想修改配置,可以考虑降级JDK版本到8(因为JDK8没有模块系统,不会出现此问题)。不过,这只是一个临时解决方案,建议最终升级Kotlin版本并正确配置模块导出。 ### 验证 进行上述更改后,重新构建项目,观察错误是否消失。 ### 注意事项 - 导出JDK内部API可能会带来安全风险,并且这些API在未来的JDK版本中可能会被移除或更改。因此,建议同时升级Kotlin版本,因为新版本可能会减少对内部API的依赖。 - 如果使用IDE(如IntelliJ IDEA),请确保IDE使用的JDK版本与构建工具(Gradle或Maven)使用的JDK版本一致,以避免因JDK版本不一致导致的问题。 通过以上步骤,应该能够解决`IllegalAccessError`问题。如果问题仍然存在,请检查是否还有其他包需要导出,并根据错误日志添加相应的导出参数。 §§相关问题§§ 1. 如何解决Kotlin kapt在其他JDK版本(如JDK 11、17)中的类似模块访问问题? 2. 除了kapt,还有哪些Java工具会因JDK模块系统出现访问错误?如何解决? 3. 在持续集成(CI)环境中如何配置Gradle或Maven以支持多版本JDK构建? </think>### 解决Java IllegalAccessError: kapt无法访问JDK内部模块的问题 当Kotlin kapt(注解处理工具)尝试访问JDK内部模块`com.sun.tools.javac`时,会因Java模块系统的封装限制触发此错误。本文将提供系统化的解决方案,参考引用[^1]的同类错误模式。 --- #### 原因分析 Java 9+的模块系统限制了内部API访问: 1. **模块隔离**:`jdk.compiler`模块未向未命名模块(kapt)导出`com.sun.tools.javac.main`包 2. **kapt依赖**:kotlin kapt需访问`JavaCompiler`等内部类生成代码 3. **JDK版本冲突**:常见于JDK 11+环境(引用[^1]展示类似错误) --- ### 解决方案(逐步执行) #### 方案1:添加模块导出指令(推荐) 在构建配置中开放JDK内部模块访问权限: **Gradle项目配置**: 1. 在`gradle.properties`中添加: ```properties org.gradle.jvmargs=\ --add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ``` 2. 或在`build.gradle`中配置kapt任务: ```groovy tasks.withType(org.jetbrains.kotlin.gradle.tasks.KaptTask).configureEach { jvmArgs += [ '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED' ] } ``` **Maven项目配置**: ```xml <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <configuration> <args> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg> <arg>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg> </args> </configuration> </plugin> ``` #### 方案2:升级Kotlinkapt版本 ```gradle // 项目级 build.gradle dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21" // 使用最新稳定版 } // 模块级 build.gradle dependencies { kapt "org.jetbrains.kotlin:kotlin-annotation-processing:1.9.21" } ``` #### 方案3:JDK版本管理 1. **降级JDK**: ```bash # 检查当前JDK版本 java -version # 切换至JDK 8 export JAVA_HOME=/path/to/jdk8 ``` 2. **多版本共存**(IntelliJ): - File > Project Structure > SDKs > 添加JDK 8 - 设置项目语言级别为8 --- ### 验证与调试 1. **清理构建**: ```bash ./gradlew clean build --info # Gradle mvn clean install -X # Maven ``` 2. **环境检查**: ```bash # 确认JAVA_HOME构建JDK一致 echo $JAVA_HOME ./gradlew -v | grep "JVM" ``` 3. **诊断未导出包**: 若出现新错误如`cannot access com.sun.tools.javac.processing`[^1],在导出列表追加: ```properties --add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED ``` --- ### 预防措施 1. **固定JDK版本**: ```dockerfile # Docker示例 FROM openjdk:11.0.20-jdk ENV JAVA_HOME=/usr/local/openjdk-11 ``` 2. **模块化声明**(JDK 16+): 在`module-info.java`中显式声明: ```java open module your.module { requires kotlin.stdlib; requires static kapt; // 显式声明kapt依赖 } ``` 3. **持续更新**: - 定期升级Kotlin([最新版本](https://kotlinlang.org/docs/releases.html)) - 使用[Gradle Toolchain](https://docs.gradle.org/current/userguide/toolchains.html)管理JDK版本 > **注意**:导出JDK内部API(`com.sun`包)存在兼容性风险,建议优先升级kapt版本
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值