赞
踩
配置环境变量JAVA_HOME CLASSPATH MVN_HOME GRADLE_HOME GLOOVY_HOME
mvn和gradle都是用来管理和编译java项目的,mvn比较老,现在一般用gradle
vscode安装extension:Extension Pack for java
设置->extension->java 修改setting.json
{
"java.jdt.ls.java.home": "D:\\Program Files\\Java\\jdk-20",
"java.semanticHighlighting.enabled": true,
"editor.suggestSelection": "first",
"vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
"java.configuration.checkProjectSettingsExclusions": false,
"git.ignoreWindowsGit27Warning": true,
"java.requirements.JDK11Warning": false,
"java.eclipse.downloadSources": true,
"java.maven.downloadSources": true,
"java.configuration.maven.globalSettings": "D:\\Program Files\\apache-maven-3.9.2\\conf\\settings.xml",
"java.debug.settings.exceptionBreakpoint.skipClasses": [
],
}
修改环境变量(JAVA_home):
idea可以直接创建,但我用的vscode,不知道怎么创建
在cmd内使用gradle命令创建(gradle init --type java-application):
执行完毕后可以看到生成了一些文件:
修改build.gradle文件:
plugins { id 'java' //配合shadowJar将依赖的jar打在一个包里 id 'com.github.johnrengelman.shadow' version '2.0.4' } group 'hyper.http.server' version '1.0-SNAPSHOT' //很多镜像被墙或者速度很慢,需要设置代理 repositories { maven { url 'https://maven.aliyun.com/repository/central/' } maven { url 'https://maven.aliyun.com/repository/public/' } maven { url 'https://maven.aliyun.com/repository/spring/' } maven { url 'https://maven.aliyun.com/repository/google/' } maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' } maven { url 'https://maven.aliyun.com/repository/spring-plugin/' } maven { url 'https://www.jitpack.io' } mavenLocal() mavenCentral() } dependencies { implementation "io.netty:netty-all:4.1.78.Final" implementation "io.netty:netty-codec-http:4.1.78.Final" implementation "io.netty.incubator:netty-incubator-codec-http3:0.0.12.Final" implementation 'io.netty.incubator:netty-incubator-codec-quic:0.0.12.Final' implementation 'io.netty.incubator:netty-incubator-codec-native-quic:0.0.28.Final' } java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } shadowJar { baseName = 'hyperhttp' version = '1.0-SNAPSHOT' classifier = null manifest { //attributes 'Main-Class': 'com.example.Main' } }
首先根据jdk环境和netty分支,选择jdk版本对应的分支,jdk换版本会有很多莫名其妙的问题。
源码路径:https://github.com/netty/netty
netty的pom.xml总指定了jdk版本:
还要下载netty-incubator-codec-quic用来编译netty-quiche-xxx.so,libquiche.so等
(建议用linux环境,windows用dll但更麻烦一些,工具安装麻烦,问题也多)
https://github.com/netty/netty-incubator-codec-quic
可以使用IntellJ的右键Dependency analazy选择正确的版本,到没有版本冲突为止
需要安装c、c++、rust和go相关的软件,包括rust(curl --proto ‘=https’ --tlsv1.2 -sSf https://sh.rustup.rs | sh)、c++(sudo apt install build-essential)、cmake(https://cmake.org/download/,apt install cmake)、Ninja(https://github.com/ninja-build/ninja/releases,apt install ninja-build)、go(apt install golang)、nasm(https://www.nasm.us/pub/nasm/releasebuilds/),autoreconf(sudo apt install -y autoconf automake libtool),还有其他工具,按照错误提示安装。
先执行(不然编译过程中下载代码会失败):
git config --global url."https://github.com/google/boringssl.git".insteadOf "https://boringssl.googlesource.com/boringssl"
在代码目录下执行:mvn compile -X(X是为了看到错误细节)
执行完会生成libquiche.so
继续执行mvn install -Dmaven.test.skip=true
执行完会生成libnetty_quiche_xxx.so,install过程中会自动将生成的库设置好动态链接:
[INFO] libtool: install: /usr/bin/install -c .libs/libnetty_quiche_linux_x86_64-0.0.46.Final.so /home/http3/netty-incubator-codec-quic-46/codec-native-quic/target/native-build/target/lib/libnetty_quiche_linux_x86_64-0.0.46.Final.so
[INFO] libtool: install: (cd /home/http3/netty-incubator-codec-quic-46/codec-native-quic/target/native-build/target/lib && { ln -s -f libnetty_quiche_linux_x86_64-0.0.46.Final.so libnetty_quiche_linux_x86_64.so || { rm -f libnetty_quiche_linux_x86_64.so && ln -s libnetty_quiche_linux_x86_64-0.0.46.Final.so libnetty_quiche_linux_x86_64.so; }; })
[INFO] libtool: install: /usr/bin/install -c .libs/libnetty_quiche_linux_x86_64.lai /home/http3/netty-incubator-codec-quic-46/codec-native-quic/target/native-build/target/lib/libnetty_quiche_linux_x86_64.la
[INFO] libtool: finish: PATH="/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/http3/jdk-20.0.1/bin:/sbin" ldconfig -n /home/http3/netty-incubator-codec-quic-46/codec-native-quic/target/native-build/target/lib
[INFO] ----------------------------------------------------------------------
[INFO] Libraries have been installed in:
[INFO] /home/http3/netty-incubator-codec-quic-46/codec-native-quic/target/native-build/target/lib
也可以将这两个so拷贝到/usr/lib/下面
(用老版本很可能编不过,因为老版本需要每个git先下载再切分支,很慢很慢,很多次成功一次,很可能切分支失败你不知道,最后就版本不对应,你也不知道,github的访问有多愁人你懂的。
很老的版本,比如我用的12,commit点都找不到了,根本不可能编的过)
在/etc/profile中添加:
export LD_LIBRARY_PATH=/usr/lib
然后source /etc/profile
./gradlew build后打包,可以看到打包的jar包:
./build/libs/hyper.jar
将hyperhttp.jar和依赖的jar都拷贝到build/libs/运行:
/mnt/d/codeC/hyperhttp# cp -f build/libs/hyperhttp.jar bin/test/hyperhttp/
//-cp后面是依赖的jar包
/mnt/d/codeC/hyperhttp/bin/test# java -verbose:class -cp "hyperhttp/*:" hyperhttp.AppServerExample
按照上文中的配置,并执行./gradlew shadowJar可以生成build/libs/hyperhttp-1.0-SNAPSHOT.jar
但是需要注意在build.gradle中配置正确的依赖包打包文件:
dependencies {
implementation "io.netty:netty-all:4.1.94.Final"
implementation "io.netty:netty-codec-http:4.1.94.Final"
implementation "io.netty.incubator:netty-incubator-codec-http3:0.0.19.Final"
implementation 'io.netty.incubator:netty-incubator-codec-classes-quic:0.0.46.Final'
//implementation 'io.netty.incubator:netty-incubator-codec-quic:0.0.19.Final'
implementation 'io.netty.incubator:netty-incubator-codec-native-quic:0.0.46.Final'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.69'
implementation 'org.bouncycastle:bcprov-jdk15on:1.69'
implementation 'org.bouncycastle:bctls-jdk15on:1.69'
implementation 'org.bouncycastle:bcutil-jdk15on:1.69'
// Use JUnit test framework.
//testImplementation 'junit:junit:4.13.2'
}
不然可能会缺失jar或者jar中class冲突。
解决方法:
在pom.xml增加:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.69</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
使用mvn compile -Dcheckstyle.skip=true 编译
解决方法:修改D:\codeC\s2\UserAgent\user-agent-app\gradle\wrapper\gradle-wrapper.Properties中的distributionUrl为当前安装的版本
解决方法:将build.gradle中id ‘com.github.johnrengelman.shadow’ version '2.0.4’删了,用不着
依赖库在setting.gradle中配置,执行gradle build(或者./gradlew build)后依赖库会下载到目录:
C:\Users(用户名).gradle\caches\modules-2\files-2.1
如果使用默认配置下载会很慢,有的依赖库下不来,需要配置国内镜像,比如阿里云:
repositories {
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/spring/' }
mavenLocal()
mavenCentral()
}
删除C:\Users\xxx\.gradle文件夹后重新执行
解决方法:跳过test–gradlew.bat build -x test
D:\tool\quickio-main>gradlew.bat publishToMavenLocal
生成结果在D:\tool\quickio-main\build\publications\maven
首先要明确找不到的库应该在哪里,是否在阿里云镜像上(在https://maven.aliyun.com/上查找)
阿里云镜像没有的话在不在别的位置,也要加入setting
比如quickio在https://www.jitpack.io(很多github的项目可能都在这个网站上发布包),就要把这个加入:
也可以本地编译后放入C盘下的缓存中
在Setting->Extension找到java相关的setting.json,里边配置了maven配置文件的路径,
将对应路径下的setting中jdk设置上。
在java的setting.json中增加"java.import.generatesMetadataFilesAtProjectRoot": true,
Caused by: java.lang.LinkageError: Possible multiple incompatible native libraries on the classpath for ‘C:\Users\llll\AppData\Local\Temp\netty_quiche_windows_x86_643357633935921649459.dll’?
Caused by: java.lang.NoSuchMethodError: Method io.netty.incubator.codec.quic.QuicheNativeStaticallyReferencedJniMethods.quicheRecvInfoOffsetofTo()I not found
这实际上是找不到quiche的JNI层,该层实现在netty-incubator-codec-quic的codec-native-quic中。
gradle build只会下载jar包(下载到C:\Users\lll.gradle\caches\modules-2\files-2.1),并不会下载其中JNI层的dll文件(在linux上是so文件),
可能需要手动编译。
下载对应版本后执行mvn build,注意将被墙的git路径替换掉,执行:
git config --global url."https://github.com/google/boringssl.git".insteadOf "https://boringssl.googlesource.com/boringssl"
或者手动修改pom.xml
注意准备好rust环境、c++环境、cmake(https://cmake.org/download/)、Ninja(https://github.com/ninja-build/ninja/releases)、go、nasm(https://www.nasm.us/pub/nasm/releasebuilds/)
代码会下载到netty-incubator-codec-quic/codec-native-quic/target下面
引用库的版本间可能有冲突,可以先通过工具解决(以下例子通过IntelliJ)
在文件上右键Analyze Dependence
这是mvn compile -X才看得到的错误
linux上使用g++,windows上使用VisualStudio下的cl.exe等,如果已经安装了c++的VisualStudio,把对应exe目录加到path里。
执行
“C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat” x86
这是由于java和maven版本不匹配,maven用的3.6.3,jdk是17,而maven3.6.x不支持jdk17
更换版本3.8.8,但只能更改path和maven_home到新的连接,如果覆盖原maven文件则出错:
mvn -v
Error: Could not find or load main class org.codehaus.plexus.classwords.launcher.Launcher
这可能是由于文件系统的问题,我把文件放在了windows D盘,linux使用可能有问题。
root@DESKTOP-JJS9ODB:/mnt/d/codeC/hyperhttp/bin/test# java -cp "hyperhttp/*:" hyperhttp.AppServerExample Exception in thread "main" java.lang.UnsatisfiedLinkError: failed to load the required native library at io.netty.incubator.codec.quic.Quic.ensureAvailability(Quic.java:78) at io.netty.incubator.codec.quic.QuicCodecBuilder.<init>(QuicCodecBuilder.java:59) at io.netty.incubator.codec.quic.QuicServerCodecBuilder.<init>(QuicServerCodecBuilder.java:48) at io.netty.incubator.codec.http3.Http3.newQuicServerCodecBuilder(Http3.java:148) at hyper.http.server.hyperHttpServer.<init>(hyperHttpServer.java:29) at hyperhttp.AppServerExample.main(AppServerExample.java:17) Caused by: java.lang.LinkageError: Possible multiple incompatible native libraries on the classpath for '/tmp/libnetty_quiche_linux_x86_649259403363156468475.so'? at io.netty.util.internal.NativeLibraryLoader.rethrowWithMoreDetailsIfPossible(NativeLibraryLoader.java:414) at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:402) at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:218) at io.netty.incubator.codec.quic.Quiche.loadNativeLibrary(Quiche.java:77) at io.netty.incubator.codec.quic.Quiche.<clinit>(Quiche.java:57) at io.netty.incubator.codec.quic.Quic.<clinit>(Quic.java:43) ... 5 more Caused by: java.lang.NoSuchMethodError: Method io.netty.incubator.codec.quic.QuicheNativeStaticallyReferencedJniMethods.quicheRecvInfoOffsetofTo()I not found at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:331) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:197) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:139) at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2404) at java
linux运行java: java -verbose:class -cp “hyperhttp/*:” hyperhttp.AppClientExample
windows也是这里失败,实际上不是在找so,而是在找class相关的jar
需要编译netty-incubator-codec-quic(maven compile -X)成功生成的codec-classes-quic/target/netty-incubator-codec-classes-quic-0.0.46.Final.jar
但有的情况下这个jar没问题也会出现这个提示,可以查看过程是不是引用错了jar,正确的应该是:
[class,load] io.netty.incubator.codec.quic.QuicheNativeStaticallyReferencedJniMethods source: file:/mnt/d/codeC/hyperhttp/bin/test/hyperhttp/netty-incubator-codec-classes-quic-0.0.46.Final.jar
另外一个jar也包含了这个class,就是netty-incubator-codec-quic-0.0.19.Final.jar,java可能会优先加载错误的jar包,删除这个jar就好了。
jar包的内容使用命令:
jar tf xxx.jar
netty这个版本依赖于jdk20(pom.xml)
还有fatal: unable to connect to github.com:
github.com[0: 20.205.243.166]: errno=Invalid argument
这很可能不是错误,就是github太难连上了,在不同的时间多试几次吧。。
java.security.cert.CertificateException: No provider succeeded to generate a self-signed certificate.
java.lang.UnsupportedOperationException: OpenJdkSelfSignedCertGenerator not supported on the used JDK version
虽然提示了jdk版本不对(不知道为什么提示,但版本确实是对的,我特意换了指定版本)
但实际上,看代码:
如果支持了BouncyCastle,就用不着走后面的流程了,
所以依赖包位置上根据对应版本的netty pom.xml拷贝几个jar包
windows位置:C:\Users\lll.m2\repository\org\bouncycastle\bcutil-jdk15on\1.69
linux位置:/root/.m2/repository/org\bouncycastle\bcutil-jdk15on\1.69
netty的pom.xml指定的版本:
pom里边指定了三个jar包,实际上拷贝完这三个jar包并不管用,还有一个bcutil-jdk15on-1.69才可以:
FAILURE: Build failed with an exception.
* Where:
Build file '/mnt/d/codeC/hyperhttp/build.gradle' line: 69
* What went wrong:
A problem occurred evaluating root project 'hyperhttp'.
> Could not set unknown property 'baseName' for task ':shadowJar' of type com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.
这可能是由于shadow比较新,
旧的ShadowJar版本使用的是baseName,但新的版本更换了方式:
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}
shadowJar {
archiveBaseName.set('hyperhttp')
archiveClassifier.set('1.0-SNAPSHOT')
archiveVersion.set('')
}
root@DESKTOP-JJS9ODB:/mnt/d/codeC/hyperhttp# ./gradlew build -X FAILURE: Build failed with an exception. * Where: Build file '/mnt/d/codeC/hyperhttp/build.gradle' * What went wrong: Could not compile build file '/mnt/d/codeC/hyperhttp/build.gradle'. > startup failed: General error during conversion: Unsupported class file major version 64 java.lang.IllegalArgumentException: Unsupported class file major version 64 at groovyjarjarasm.asm.ClassReader.<init>(ClassReader.java:199) at groovyjarjarasm.asm.ClassReader.<init>(ClassReader.java:180) at groovyjarjarasm.asm.ClassReader.<init>(ClassReader.java:166) at groovyjarjarasm.asm.ClassReader.<init>(ClassReader.java:287) at org.codehaus.groovy.ast.decompiled.AsmDecompiler.parseClass(AsmDecompiler.java:81) at org.codehaus.groovy.control.ClassNodeResolver.findDecompiled(ClassNodeResolver.java:251) at org.codehaus.groovy.control.ClassNodeResolver.tryAsLoaderClassOrScript(ClassNodeResolver.java:189) at org.codehaus.groovy.control.ClassNodeResolver.findClassNode(ClassNodeResolver.java:169) at org.codehaus.groovy.control.ClassNodeResolver.resolveName(ClassNodeResolver.java:125) at org.codehaus.groovy.ast.decompiled.AsmReferenceResolver.resolveClassNullable(AsmReferenceResolver.java:57) at org.codehaus.groovy.ast.decompiled.AsmReferenceResolver.resolveClass(AsmReferenceResolver.java:44)
这是由于jdk版本与gradle版本不配套,可以修改gradle\wrapper下的配置文件到相应的版本,
build时就会自动下载响应的gradle版本(我是jdk20, gradle8.2, shadow8.1.1):
这个路径可能会下载失败,提示Exception in thread “main” java.io.IOException: Downloading from https://services.gradle.org/distributions/gradle-7.5.1-bin.zip failed: timeout
可以换成distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.5.1-bin.zip
FAILURE: Build failed with an exception.
* Where:
Build file '/mnt/d/codeC/hyperhttp/build.gradle' line: 12
* What went wrong:
An exception occurred applying plugin request [id: 'com.github.johnrengelman.shadow', version: '2.0.4']
> Failed to apply plugin class 'com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin'.
> You can't map a property that does not exist: propertyName=classifier
可能是由于shadow版本和gradle不配套,如果gradle用8.x.x,那么shadow相应的一般也是8.x.x
一般是vscode中JAVA_HOME配置有问题,首先确认环境变量中java home配置是否正确,然后确认vscode中setting->java->setting.json中"java.jdt.ls.java.home"是否正确。
如果都没有问题,那么看下项目里边是否指定了jdk版本,比如build.gradle中:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。