Ensure we only register native methods once (#10876)

Motivation:

We need to ensure we only register native methods once as otherwise we may end up in an "invalid" state. The problem here was that before it was basically the responsibility the user of transport-native-unix-common to register the methods. This is error prone as there may be multiple users of these on the classpath at the same time.

Modifications:

- Provide a way to init native lib without register the native methods of the provided classes. This is needed to be able to re-use functionality which is exposed to our internal native code
- Use flatten plugin to correctly resolve classifier and so have the correct dependency
- Call Unix.* method to ensure we register the methods correctly once
- Include native lib as well in the native jars of unix-common

Result:

Be able to have multiple artifacts of the classpath that depends on the unix-common. Related to https://github.com/netty/netty-incubator-transport-io_uring/issues/15
This commit is contained in:
Norman Maurer 2020-12-18 10:37:49 +01:00 committed by GitHub
parent 5c1613df81
commit 7fb62a93b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 795 additions and 345 deletions

View File

@ -61,6 +61,27 @@
<dependencies>
<!-- Depend on all our native jars -->
<!-- As this is executed on either macOS or Linux we directly need to specify the classifier -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<classifier>linux-x86_64</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<classifier>linux-aarch_64</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<classifier>osx-x86_64</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
@ -97,6 +118,27 @@
<dependencies>
<!-- Depend on all our native jars -->
<!-- As this is executed on either macOS or Linux we directly need to specify the classifier -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<classifier>linux-x86_64</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<classifier>linux-aarch_64</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<classifier>osx-x86_64</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
@ -128,7 +170,7 @@
</dependencies>
</profile>
<!-- The linux profile will only include the native jar for epol to the all jar.
<!-- The linux profile will only include the native jar for epoll to the all jar.
If you want to also include the native jar for kqueue use -Puber.
-->
<profile>
@ -140,6 +182,14 @@
</activation>
<dependencies>
<!-- All release modules -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
@ -175,6 +225,14 @@
</activation>
<dependencies>
<!-- All release modules -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>
@ -209,6 +267,14 @@
</activation>
<dependencies>
<!-- All release modules -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>
@ -236,6 +302,14 @@
</activation>
<dependencies>
<!-- All release modules -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>

27
pom.xml
View File

@ -1309,6 +1309,33 @@
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<!-- enable flattening -->
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<!-- ensure proper cleanup -->
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
<configuration>
<flattenMode>oss</flattenMode>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
<!-- keep surefire and failsafe in sync -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>

View File

@ -124,11 +124,23 @@
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<!--
The unix-common with classifier dependency is optional because it is not a runtime dependency, but a build time
dependency to get the static library which is built directly into the shared library generated by this project.
-->
<optional>true</optional>
</dependency>
</dependencies>
</profile>
<profile>
<!--
For non-classifier native builds we should depend on netty-transport-native-unix-common without the
classifier. This profile will be disabled by the other profiles when the native bits will be build.
-->
<id>non-native</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</profile>
@ -156,15 +168,16 @@
<artifactId>netty-resolver-dns</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- We need to use the flatten plugin so the classifier portion of the dependency is resolved-->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>

View File

@ -15,6 +15,7 @@
*/
package io.netty.resolver.dns.macos;
import io.netty.channel.unix.Unix;
import io.netty.resolver.dns.DnsServerAddressStream;
import io.netty.resolver.dns.DnsServerAddressStreamProvider;
import io.netty.resolver.dns.DnsServerAddressStreamProviders;
@ -53,6 +54,7 @@ public final class MacOSDnsServerAddressStreamProvider implements DnsServerAddre
static {
Throwable cause = null;
try {
Unix.ensureAvailability();
loadNativeLibrary();
} catch (Throwable error) {
cause = error;

View File

@ -241,6 +241,7 @@
<dependencySet>
<scope>test</scope>
</dependencySet>
<separator>${line.separator}</separator>
</configuration>
</execution>
</executions>

View File

@ -202,11 +202,6 @@
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<!--
The unix-common with classifier dependency is optional because it is not a runtime dependency, but a build time
dependency to get the static library which is built directly into the shared library generated by this project.
-->
<optional>true</optional>
</dependency>
</dependencies>
</profile>
@ -351,11 +346,23 @@
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<!--
The unix-common with classifier dependency is optional because it is not a runtime dependency, but a build time
dependency to get the static library which is built directly into the shared library generated by this project.
-->
<optional>true</optional>
</dependency>
</dependencies>
</profile>
<profile>
<!--
For non-classifier native builds we should depend on netty-transport-native-unix-common without the
classifier. This profile will be disabled by the other profiles when the native bits will be build.
-->
<id>non-native</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</profile>
@ -377,11 +384,6 @@
<artifactId>netty-transport</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-testsuite</artifactId>
@ -405,6 +407,11 @@
<build>
<plugins>
<!-- We need to use the flatten plugin so the classifier portion of the dependency is resolved-->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
</plugin>
<!-- Also include c files in source jar -->
<plugin>
<groupId>org.codehaus.mojo</groupId>

View File

@ -16,6 +16,7 @@
package io.netty.channel.epoll;
import io.netty.channel.unix.FileDescriptor;
import io.netty.channel.unix.Unix;
import io.netty.util.internal.SystemPropertyUtil;
/**
@ -36,6 +37,7 @@ public final class Epoll {
FileDescriptor epollFd = null;
FileDescriptor eventFd = null;
try {
Unix.ensureAvailability();
epollFd = Native.newEpollCreate();
eventFd = Native.newEventFd();
} catch (Throwable t) {

View File

@ -62,7 +62,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
@ -129,11 +128,6 @@
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<!--
The unix-common with classifier dependency is optional because it is not a runtime dependency, but a build time
dependency to get the static library which is built directly into the shared library generated by this project.
-->
<optional>true</optional>
</dependency>
</dependencies>
</profile>
@ -235,11 +229,6 @@
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<!--
The unix-common with classifier dependency is optional because it is not a runtime dependency, but a build time
dependency to get the static library which is built directly into the shared library generated by this project.
-->
<optional>true</optional>
</dependency>
</dependencies>
</profile>
@ -341,11 +330,23 @@
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
<classifier>${jni.classifier}</classifier>
<!--
The unix-common with classifier dependency is optional because it is not a runtime dependency, but a build time
dependency to get the static library which is built directly into the shared library generated by this project.
-->
<optional>true</optional>
</dependency>
</dependencies>
</profile>
<profile>
<!--
For non-classifier native builds we should depend on netty-transport-native-unix-common without the
classifier. This profile will be disabled by the other profiles when the native bits will be build.
-->
<id>non-native</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</profile>
@ -381,11 +382,6 @@
<artifactId>netty-transport</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-testsuite</artifactId>
@ -408,6 +404,12 @@
<build>
<plugins>
<!-- We need to use the flatten plugin so the classifier portion of the dependency is resolved-->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
</plugin>
<!-- Also include c files in source jar -->
<plugin>
<groupId>org.codehaus.mojo</groupId>

View File

@ -16,6 +16,7 @@
package io.netty.channel.kqueue;
import io.netty.channel.unix.FileDescriptor;
import io.netty.channel.unix.Unix;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.UnstableApi;
@ -34,6 +35,7 @@ public final class KQueue {
} else {
FileDescriptor kqueueFd = null;
try {
Unix.ensureAvailability();
kqueueFd = Native.newKQueue();
} catch (Throwable t) {
cause = t;

View File

@ -23,12 +23,13 @@
# LIB_NAME - the name of the native library
SRC_DIR = src/main/c
SRC_INTERNAL_DIR = src/main/c/internal
UTIL_SRC_DIR = target/netty-jni-util/src/c
JNI_INCLUDE_DIR = $(JAVA_HOME)/include
JNI_INCLUDES = -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/$(JNI_PLATFORM)
LIB = $(LIB_DIR)/$(LIB_NAME).a
CFLAGS += $(JNI_INCLUDES) -I$(UTIL_SRC_DIR)
CFLAGS += $(JNI_INCLUDES) -I$(UTIL_SRC_DIR) -I$(SRC_INTERNAL_DIR)
SRCS = $(wildcard $(SRC_DIR)/*.c)
UTIL_SRCS = $(wildcard $(UTIL_SRC_DIR)/*.c)

View File

@ -44,6 +44,11 @@
<nativeLibOnlyDir>${project.build.directory}/native-lib-only</nativeLibOnlyDir>
<defaultJarFile>${project.build.directory}/${project.build.finalName}.jar</defaultJarFile>
<nativeJarFile>${project.build.directory}/${project.build.finalName}-${jni.classifier}.jar</nativeJarFile>
<generatedSourcesDir>${project.build.directory}/generated-sources</generatedSourcesDir>
<cflags>-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${project.basedir}/src/main/c</cflags>
<ldflags>-Wl,--no-as-needed -lrt</ldflags>
<nativeLibArch>${os.detected.arch}</nativeLibArch>
<build.native>false</build.native>
</properties>
<build>
@ -102,73 +107,10 @@
</os>
</activation>
<properties>
<build.native>true</build.native>
<exe.compiler>clang</exe.compiler>
<jni.platform>darwin</jni.platform>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Build the additional JAR that contains the native library. -->
<execution>
<id>native-jar</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy todir="${nativeJarWorkdir}">
<zipfileset src="${defaultJarFile}" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeLibOnlyDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+)$" to="META-INF/native/lib/\1" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${jniUtilIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<jar destfile="${nativeJarFile}" manifest="${nativeJarWorkdir}/META-INF/MANIFEST.MF" basedir="${nativeJarWorkdir}" index="true" excludes="META-INF/MANIFEST.MF,META-INF/INDEX.LIST" />
<attachartifact file="${nativeJarFile}" classifier="${jni.classifier}" type="jar" />
</target>
</configuration>
</execution>
<!-- invoke the make file to build a static library -->
<execution>
<id>build-native-lib</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<exec executable="${exe.make}" failonerror="true" resolveexecutable="true">
<env key="CC" value="${exe.compiler}" />
<env key="AR" value="${exe.archiver}" />
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
<!-- support for __attribute__((weak_import)) by the linker was added in 10.2 so ensure we
explicitly set the target platform. Otherwise we may get fatal link errors due to weakly linked
methods which are not expected to be present on MacOS (e.g. accept4). -->
<env key="MACOSX_DEPLOYMENT_TARGET" value="10.2" />
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>linux</id>
@ -180,136 +122,17 @@
<properties>
<jni.platform>linux</jni.platform>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Build the additional JAR that contains the native library. -->
<execution>
<id>native-jar</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy todir="${nativeJarWorkdir}">
<zipfileset src="${defaultJarFile}" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeLibOnlyDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+)$" to="META-INF/native/lib/\1" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${jniUtilIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<jar destfile="${nativeJarFile}" manifest="${nativeJarWorkdir}/META-INF/MANIFEST.MF" basedir="${nativeJarWorkdir}" index="true" excludes="META-INF/MANIFEST.MF,META-INF/INDEX.LIST" />
<attachartifact file="${nativeJarFile}" classifier="${jni.classifier}" type="jar" />
</target>
</configuration>
</execution>
<!-- invoke the make file to build a static library -->
<execution>
<id>build-native-lib</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<exec executable="${exe.make}" failonerror="true" resolveexecutable="true">
<env key="CC" value="${exe.compiler}" />
<env key="AR" value="${exe.archiver}" />
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>linux-aarch64</id>
<properties>
<!-- use aarch_64 as this is also what os.detected.arch will use on an aarch64 system -->
<nativeLibArch>aarch_64</nativeLibArch>
<jni.classifier>${os.detected.name}-aarch_64</jni.classifier>
<jni.platform>linux</jni.platform>
<exe.compiler>aarch64-linux-gnu-gcc</exe.compiler>
<exe.archiver>aarch64-linux-gnu-ar</exe.archiver>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Build the additional JAR that contains the native library. -->
<execution>
<id>native-jar</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy todir="${nativeJarWorkdir}">
<zipfileset src="${defaultJarFile}" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeLibOnlyDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+)$" to="META-INF/native/lib/\1" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${jniUtilIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<jar destfile="${nativeJarFile}" manifest="${nativeJarWorkdir}/META-INF/MANIFEST.MF" basedir="${nativeJarWorkdir}" index="true" excludes="META-INF/MANIFEST.MF,META-INF/INDEX.LIST" />
<attachartifact file="${nativeJarFile}" classifier="${jni.classifier}" type="jar" />
</target>
</configuration>
</execution>
<!-- invoke the make file to build a static library -->
<execution>
<id>build-native-lib</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<exec executable="${exe.make}" failonerror="true" resolveexecutable="true">
<env key="CC" value="${exe.compiler}" />
<env key="AR" value="${exe.archiver}" />
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>freebsd</id>
@ -324,66 +147,6 @@
<exe.make>gmake</exe.make>
<jni.platform>freebsd</jni.platform>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Build the additional JAR that contains the native library. -->
<execution>
<id>native-jar</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy todir="${nativeJarWorkdir}">
<zipfileset src="${defaultJarFile}" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeLibOnlyDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+)$" to="META-INF/native/lib/\1" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<jar destfile="${nativeJarFile}" manifest="${nativeJarWorkdir}/META-INF/MANIFEST.MF" basedir="${nativeJarWorkdir}" index="true" excludes="META-INF/MANIFEST.MF,META-INF/INDEX.LIST" />
<attachartifact file="${nativeJarFile}" classifier="${jni.classifier}" type="jar" />
</target>
</configuration>
</execution>
<!-- invoke the make file to build a static library -->
<execution>
<id>build-native-lib</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<exec executable="${exe.make}" failonerror="true" resolveexecutable="true">
<env key="CC" value="${exe.compiler}" />
<env key="AR" value="${exe.archiver}" />
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>openbsd</id>
@ -398,6 +161,15 @@
<exe.make>gmake</exe.make>
<jni.platform>openbsd</jni.platform>
</properties>
</profile>
<profile>
<id>build.native</id>
<activation>
<os>
<family>!windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
@ -421,7 +193,8 @@
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${nativeIncludeDir}" />
<regexpmapper handledirsep="yes" from="^(?:[^/]+/)*([^/]+).h$" to="META-INF/native/include/\1.h" />
<!-- Only one level as we don't want to include the internal headers-->
<regexpmapper handledirsep="yes" from="^([^/]+).h$" to="META-INF/native/include/\1.h" />
</copy>
<copy todir="${nativeJarWorkdir}" includeEmptyDirs="false">
<zipfileset dir="${jniUtilIncludeDir}" />
@ -447,15 +220,69 @@
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="CFLAGS" value="${cflags}" />
<env key="LDFLAGS" value="${ldflags}" />
<env key="LIB_NAME" value="${nativeLibName}" />
<!-- support for __attribute__((weak_import)) by the linker was added in 10.2 so ensure we
explicitly set the target platform. Otherwise we may get fatal link errors due to weakly linked
methods which are not expected to be present on MacOS (e.g. accept4). -->
<env key="MACOSX_DEPLOYMENT_TARGET" value="10.2" />
</exec>
</target>
</configuration>
</execution>
<execution>
<id>copy-src</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Copy all of the c code -->
<delete dir="${generatedSourcesDir}" quiet="true" />
<copy todir="${generatedSourcesDir}/c" verbose="true">
<fileset dir="${project.basedir}/src/main/c" />
</copy>
<copy todir="${generatedSourcesDir}/c" verbose="true">
<fileset dir="${jniUtilIncludeDir}" />
</copy>
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<executions>
<execution>
<id>build-native-lib</id>
<configuration>
<name>netty_transport_native_unix_${os.detected.name}_${nativeLibArch}</name>
<nativeSourceDirectory>${generatedSourcesDir}</nativeSourceDirectory>
<libDirectory>${project.build.outputDirectory}</libDirectory>
<!-- We use Maven's artifact classifier instead.
This hack will make the hawtjni plugin to put the native library
under 'META-INF/native' rather than 'META-INF/native/${platform}'. -->
<platform>.</platform>
<forceConfigure>true</forceConfigure>
<forceAutogen>true</forceAutogen>
<configureArgs>
<arg>MACOSX_DEPLOYMENT_TARGET=10.2</arg>
<arg>CFLAGS=${cflags}</arg>
</configureArgs>
</configuration>
<goals>
<goal>generate</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef NETTY_UNIX_BUFFER_INTERNAL_H_
#define NETTY_UNIX_BUFFER_INTERNAL_H_
#include <jni.h>
// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods.
jint netty_unix_buffer_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix);
void netty_unix_buffer_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix);
#endif /* NETTY_UNIX_BUFFER_INTERNAL_H_ */

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef NETTY_UNIX_ERRORS_INTERNAL_H_
#define NETTY_UNIX_ERRORS_INTERNAL_H_
#include <jni.h>
// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods.
jint netty_unix_errors_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix);
void netty_unix_errors_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix);
#endif /* NETTY_UNIX_ERRORS_INTERNAL_H_ */

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef NETTY_UNIX_FILEDESCRIPTOR_INTERNAL_H_
#define NETTY_UNIX_FILEDESCRIPTOR_INTERNAL_H_
#include <jni.h>
// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods.
jint netty_unix_filedescriptor_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix);
void netty_unix_filedescriptor_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix);
#endif /* NETTY_UNIX_FILEDESCRIPTOR_INTERNAL_H_ */

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef NETTY_UNIX_LIMITS_INTERNAL_H_
#define NETTY_UNIX_LIMITS_INTERNAL_H_
#include <jni.h>
// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods.
jint netty_unix_limits_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix);
void netty_unix_limits_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix);
#endif /* NETTY_UNIX_LIMITS_INTERNAL_H_ */

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef NETTY_UNIX_SOCKET_INTERNAL_H_
#define NETTY_UNIX_SOCKET_INTERNAL_H_
#include <jni.h>
// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods.
jint netty_unix_socket_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix);
void netty_unix_socket_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix);
#endif /* NETTY_UNIX_SOCKET_INTERNAL_H_ */

View File

@ -17,6 +17,7 @@
#include "netty_unix_util.h"
#include "netty_unix_buffer.h"
#include "netty_jni_util.h"
#include "internal/netty_unix_buffer_internal.h"
#define BUFFER_CLASSNAME "io/netty/channel/unix/Buffer"
@ -39,19 +40,40 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = {
static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]);
// JNI Method Registration Table End
jint netty_unix_buffer_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
// We must register the statically referenced methods first!
if (netty_jni_util_register_natives(env,
packagePrefix,
BUFFER_CLASSNAME,
statically_referenced_fixed_method_table,
statically_referenced_fixed_method_table_size) != 0) {
return JNI_ERR;
static jint netty_unix_buffer_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) {
if (registerNative) {
// We must register the statically referenced methods first!
if (netty_jni_util_register_natives(env,
packagePrefix,
BUFFER_CLASSNAME,
statically_referenced_fixed_method_table,
statically_referenced_fixed_method_table_size) != 0) {
return JNI_ERR;
}
}
return NETTY_JNI_UTIL_JNI_VERSION;
}
void netty_unix_buffer_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_jni_util_unregister_natives(env, packagePrefix, BUFFER_CLASSNAME);
static void netty_unix_buffer_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) {
if (unregisterNative) {
netty_jni_util_unregister_natives(env, packagePrefix, BUFFER_CLASSNAME);
}
}
jint netty_unix_buffer_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_buffer_JNI_OnLoad0(env, packagePrefix, 0);
}
void netty_unix_buffer_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_buffer_JNI_OnUnLoad0(env, packagePrefix, 0);
}
jint netty_unix_buffer_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_buffer_JNI_OnLoad0(env, packagePrefix, 1);
}
void netty_unix_buffer_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_buffer_JNI_OnUnLoad0(env, packagePrefix, 1);
}

View File

@ -21,6 +21,7 @@
#include "netty_unix_jni.h"
#include "netty_unix_util.h"
#include "netty_jni_util.h"
#include "internal/netty_unix_errors_internal.h"
#define ERRORS_CLASSNAME "io/netty/channel/unix/ErrorsStaticallyReferencedJniMethods"
@ -212,15 +213,17 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = {
static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]);
// JNI Method Registration Table End
jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
static jint netty_unix_errors_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) {
char* nettyClassName = NULL;
// We must register the statically referenced methods first!
if (netty_jni_util_register_natives(env,
packagePrefix,
ERRORS_CLASSNAME,
statically_referenced_fixed_method_table,
statically_referenced_fixed_method_table_size) != 0) {
return JNI_ERR;
if (registerNative) {
// We must register the statically referenced methods first!
if (netty_jni_util_register_natives(env,
packagePrefix,
ERRORS_CLASSNAME,
statically_referenced_fixed_method_table,
statically_referenced_fixed_method_table_size) != 0) {
return JNI_ERR;
}
}
NETTY_JNI_UTIL_LOAD_CLASS(env, oomErrorClass, "java/lang/OutOfMemoryError", error);
@ -244,7 +247,7 @@ error:
return JNI_ERR;
}
void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
static void netty_unix_errors_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) {
// delete global references so the GC can collect them
NETTY_JNI_UTIL_UNLOAD_CLASS(env, oomErrorClass);
NETTY_JNI_UTIL_UNLOAD_CLASS(env, runtimeExceptionClass);
@ -253,5 +256,23 @@ void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
NETTY_JNI_UTIL_UNLOAD_CLASS(env, portUnreachableExceptionClass);
NETTY_JNI_UTIL_UNLOAD_CLASS(env, closedChannelExceptionClass);
netty_jni_util_unregister_natives(env, packagePrefix, ERRORS_CLASSNAME);
if (unregisterNative) {
netty_jni_util_unregister_natives(env, packagePrefix, ERRORS_CLASSNAME);
}
}
jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_errors_JNI_OnLoad0(env, packagePrefix, 0);
}
void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_errors_JNI_OnUnLoad0(env, packagePrefix, 0);
}
jint netty_unix_errors_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_errors_JNI_OnLoad0(env, packagePrefix, 1);
}
void netty_unix_errors_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_errors_JNI_OnUnLoad0(env, packagePrefix, 1);
}

View File

@ -27,6 +27,8 @@
#include "netty_unix_util.h"
#include "netty_jni_util.h"
#include "internal/netty_unix_filedescriptor_internal.h"
#define FILEDESCRIPTOR_CLASSNAME "io/netty/channel/unix/FileDescriptor"
static jmethodID posId = NULL;
@ -278,11 +280,13 @@ static const JNINativeMethod method_table[] = {
static const jint method_table_size = sizeof(method_table) / sizeof(method_table[0]);
// JNI Method Registration Table End
jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
static jint netty_unix_filedescriptor_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) {
int ret = JNI_ERR;
void* mem = NULL;
if (netty_jni_util_register_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME, method_table, method_table_size) != 0) {
goto done;
if (registerNative) {
if (netty_jni_util_register_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME, method_table, method_table_size) != 0) {
goto done;
}
}
if ((mem = malloc(1)) == NULL) {
goto done;
@ -316,6 +320,24 @@ done:
return ret;
}
void netty_unix_filedescriptor_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_jni_util_unregister_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME);
static void netty_unix_filedescriptor_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) {
if (unregisterNative) {
netty_jni_util_unregister_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME);
}
}
jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_filedescriptor_JNI_OnLoad0(env, packagePrefix, 0);
}
void netty_unix_filedescriptor_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_filedescriptor_JNI_OnUnLoad0(env, packagePrefix, 0);
}
jint netty_unix_filedescriptor_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_filedescriptor_JNI_OnLoad0(env, packagePrefix, 1);
}
void netty_unix_filedescriptor_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_filedescriptor_JNI_OnUnLoad0(env, packagePrefix, 1);
}

View File

@ -21,6 +21,7 @@
#include "netty_unix_limits.h"
#include "netty_unix_util.h"
#include "netty_jni_util.h"
#include "internal/netty_unix_limits_internal.h"
#define LIMITS_CLASSNAME "io/netty/channel/unix/LimitsStaticallyReferencedJniMethods"
@ -69,19 +70,39 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = {
static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]);
// JNI Method Registration Table End
jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
// We must register the statically referenced methods first!
if (netty_jni_util_register_natives(env,
packagePrefix,
LIMITS_CLASSNAME,
statically_referenced_fixed_method_table,
statically_referenced_fixed_method_table_size) != 0) {
return JNI_ERR;
static jint netty_unix_limits_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) {
if (registerNative) {
// We must register the statically referenced methods first!
if (netty_jni_util_register_natives(env,
packagePrefix,
LIMITS_CLASSNAME,
statically_referenced_fixed_method_table,
statically_referenced_fixed_method_table_size) != 0) {
return JNI_ERR;
}
}
return NETTY_JNI_UTIL_JNI_VERSION;
}
void netty_unix_limits_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_jni_util_unregister_natives(env, packagePrefix, LIMITS_CLASSNAME);
static void netty_unix_limits_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) {
if (unregisterNative) {
netty_jni_util_unregister_natives(env, packagePrefix, LIMITS_CLASSNAME);
}
}
jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_limits_JNI_OnLoad0(env, packagePrefix, 0);
}
void netty_unix_limits_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_limits_JNI_OnUnLoad0(env, packagePrefix, 0);
}
jint netty_unix_limits_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_limits_JNI_OnLoad0(env, packagePrefix, 1);
}
void netty_unix_limits_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_limits_JNI_OnUnLoad0(env, packagePrefix, 1);
}

View File

@ -0,0 +1,124 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include <jni.h>
#include "netty_unix_buffer.h"
#include "netty_unix_errors.h"
#include "netty_unix_filedescriptor.h"
#include "netty_unix_jni.h"
#include "netty_unix_limits.h"
#include "netty_unix_socket.h"
#include "netty_unix_util.h"
#include "internal/netty_unix_buffer_internal.h"
#include "internal/netty_unix_errors_internal.h"
#include "internal/netty_unix_filedescriptor_internal.h"
#include "internal/netty_unix_limits_internal.h"
#include "internal/netty_unix_socket_internal.h"
// Add define if NETTY_BUILD_STATIC is defined so it is picked up in netty_jni_util.c
#ifdef NETTY_BUILD_STATIC
#define NETTY_JNI_UTIL_BUILD_STATIC
#endif
static jint netty_unix_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
int ret = JNI_ERR;
int limitsOnLoadCalled = 0;
int errorsOnLoadCalled = 0;
int filedescriptorOnLoadCalled = 0;
int socketOnLoadCalled = 0;
int bufferOnLoadCalled = 0;
// Load all c modules that we depend upon
if (netty_unix_limits_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
goto done;
}
limitsOnLoadCalled = 1;
if (netty_unix_errors_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
goto done;
}
errorsOnLoadCalled = 1;
if (netty_unix_filedescriptor_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
goto done;
}
filedescriptorOnLoadCalled = 1;
if (netty_unix_socket_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
goto done;
}
socketOnLoadCalled = 1;
if (netty_unix_buffer_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
goto done;
}
bufferOnLoadCalled = 1;
ret = NETTY_JNI_UTIL_JNI_VERSION;
done:
if (ret == JNI_ERR) {
if (limitsOnLoadCalled == 1) {
netty_unix_limits_internal_JNI_OnUnLoad(env, packagePrefix);
}
if (errorsOnLoadCalled == 1) {
netty_unix_errors_internal_JNI_OnUnLoad(env, packagePrefix);
}
if (filedescriptorOnLoadCalled == 1) {
netty_unix_filedescriptor_internal_JNI_OnUnLoad(env, packagePrefix);
}
if (socketOnLoadCalled == 1) {
netty_unix_socket_internal_JNI_OnUnLoad(env, packagePrefix);
}
if (bufferOnLoadCalled == 1) {
netty_unix_buffer_internal_JNI_OnUnLoad(env, packagePrefix);
}
}
return ret;
}
static void netty_unix_native_JNI_OnUnload(JNIEnv* env, const char* packagePrefix) {
netty_unix_limits_internal_JNI_OnUnLoad(env, packagePrefix);
netty_unix_errors_internal_JNI_OnUnLoad(env, packagePrefix);
netty_unix_filedescriptor_internal_JNI_OnUnLoad(env, packagePrefix);
netty_unix_socket_internal_JNI_OnUnLoad(env, packagePrefix);
netty_unix_buffer_internal_JNI_OnUnLoad(env, packagePrefix);
}
// Invoked by the JVM when statically linked
// We build with -fvisibility=hidden so ensure we mark everything that needs to be visible with JNIEXPORT
// https://mail.openjdk.java.net/pipermail/core-libs-dev/2013-February/014549.html
// Invoked by the JVM when statically linked
JNIEXPORT jint JNI_OnLoad_netty_transport_native_unix(JavaVM* vm, void* reserved) {
return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_unix", netty_unix_native_JNI_OnLoad);
}
// Invoked by the JVM when statically linked
JNIEXPORT void JNI_OnUnload_netty_transport_native_unix(JavaVM* vm, void* reserved) {
netty_jni_util_JNI_OnUnload(vm, reserved, netty_unix_native_JNI_OnUnload);
}
#ifndef NETTY_BUILD_STATIC
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_unix", netty_unix_native_JNI_OnLoad);
}
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) {
netty_jni_util_JNI_OnUnload(vm, reserved, netty_unix_native_JNI_OnUnload);
}
#endif /* NETTY_BUILD_STATIC */

View File

@ -32,6 +32,8 @@
#include "netty_unix_util.h"
#include "netty_jni_util.h"
#include "internal/netty_unix_socket_internal.h"
#define SOCKET_CLASSNAME "io/netty/channel/unix/Socket"
// Define SO_REUSEPORT if not found to fix build issues.
// See https://github.com/netty/netty/issues/2558
@ -1053,20 +1055,23 @@ error:
// JNI Method Registration Table End
jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
static jint netty_unix_socket_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) {
int ret = JNI_ERR;
char* nettyClassName = NULL;
void* mem = NULL;
JNINativeMethod* dynamicMethods = createDynamicMethodsTable(packagePrefix);
if (dynamicMethods == NULL) {
goto done;
}
if (netty_jni_util_register_natives(env,
packagePrefix,
SOCKET_CLASSNAME,
dynamicMethods,
dynamicMethodsTableSize()) != 0) {
goto done;
JNINativeMethod* dynamicMethods = NULL;
if (registerNative) {
dynamicMethods = createDynamicMethodsTable(packagePrefix);
if (dynamicMethods == NULL) {
goto done;
}
if (netty_jni_util_register_natives(env,
packagePrefix,
SOCKET_CLASSNAME,
dynamicMethods,
dynamicMethodsTableSize()) != 0) {
goto done;
}
}
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress", nettyClassName, done);
@ -1095,15 +1100,36 @@ jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
ret = NETTY_JNI_UTIL_JNI_VERSION;
done:
netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize());
if (registerNative) {
netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize());
}
free(nettyClassName);
free(mem);
return ret;
}
void netty_unix_socket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
static void netty_unix_socket_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) {
NETTY_JNI_UTIL_UNLOAD_CLASS(env, datagramSocketAddressClass);
NETTY_JNI_UTIL_UNLOAD_CLASS(env, inetSocketAddressClass);
netty_jni_util_unregister_natives(env, packagePrefix, SOCKET_CLASSNAME);
if (unregisterNative) {
netty_jni_util_unregister_natives(env, packagePrefix, SOCKET_CLASSNAME);
}
}
jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_socket_JNI_OnLoad0(env, packagePrefix, 0);
}
void netty_unix_socket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_socket_JNI_OnUnLoad0(env, packagePrefix, 0);
}
jint netty_unix_socket_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return netty_unix_socket_JNI_OnLoad0(env, packagePrefix, 1);
}
void netty_unix_socket_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
netty_unix_socket_JNI_OnUnLoad0(env, packagePrefix, 1);
}

View File

@ -51,6 +51,7 @@ public class FileDescriptor {
final int fd;
public FileDescriptor(int fd) {
Unix.ensureAvailability();
checkPositiveOrZero(fd, "fd");
this.fd = fd;
}

View File

@ -66,7 +66,7 @@ public final class IovArray implements MessageProcessor {
private final ByteBuf memory;
private int count;
private long size;
private long maxBytes = SSIZE_MAX;
private long maxBytes;
public IovArray() {
this(Unpooled.wrappedBuffer(Buffer.allocateDirectWithNativeOrder(MAX_CAPACITY)).setIndex(0, 0));
@ -74,6 +74,7 @@ public final class IovArray implements MessageProcessor {
@SuppressWarnings("deprecation")
public IovArray(ByteBuf memory) {
Unix.ensureAvailability();
assert memory.writerIndex() == 0;
assert memory.readerIndex() == 0;
this.memory = PlatformDependent.hasUnsafe() ? memory : memory.order(
@ -84,6 +85,7 @@ public final class IovArray implements MessageProcessor {
// Fallback to using JNI as we were not be able to access the address otherwise.
memoryAddress = Buffer.memoryAddress(memory.internalNioBuffer(0, memory.capacity()));
}
maxBytes = SSIZE_MAX;
}
public void clear() {

View File

@ -0,0 +1,128 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.unix;
import io.netty.util.internal.NativeLibraryLoader;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.IOException;
import java.nio.channels.Selector;
import java.util.Locale;
/**
* Tells if <a href="https://netty.io/wiki/native-transports.html">{@code netty-transport-native-unix}</a> is
* supported.
*/
public final class Unix {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Unix.class);
private static final Throwable UNAVAILABILITY_CAUSE;
static {
Throwable cause = null;
Selector selector = null;
try {
// We call Selector.open() as this will under the hood cause IOUtil to be loaded.
// This is a workaround for a possible classloader deadlock that could happen otherwise:
//
// See https://github.com/netty/netty/issues/10187
selector = Selector.open();
} catch (IOException ignore) {
// Just ignore
}
try {
try {
// First, try calling a side-effect free JNI method to see if the library was already
// loaded by the application.
LimitsStaticallyReferencedJniMethods.udsSunPathSize();
} catch (UnsatisfiedLinkError ignore) {
// The library was not previously loaded, load it now.
loadNativeLibrary();
} finally {
try {
if (selector != null) {
selector.close();
}
} catch (IOException ignore) {
// Just ignore
}
}
Socket.initialize();
} catch (Throwable error) {
cause = error;
}
UNAVAILABILITY_CAUSE = cause;
}
private static void loadNativeLibrary() {
String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim();
if (!name.startsWith("linux") && !name.startsWith("osx") && !name.startsWith("mac")
&& !name.endsWith("bsd")) {
throw new IllegalStateException("Only supported on Linux/MacOS/BSD");
}
String staticLibName = "netty_transport_native_unix";
String sharedLibName = staticLibName + '_' + PlatformDependent.normalizedOs() +
'_' + PlatformDependent.normalizedArch();
ClassLoader cl = PlatformDependent.getClassLoader(Unix.class);
try {
NativeLibraryLoader.load(sharedLibName, cl);
} catch (UnsatisfiedLinkError e1) {
try {
NativeLibraryLoader.load(staticLibName, cl);
logger.debug("Failed to load {}", sharedLibName, e1);
} catch (UnsatisfiedLinkError e2) {
ThrowableUtil.addSuppressed(e1, e2);
throw e1;
}
}
}
/**
* Returns {@code true} if and only if the <a href="https://netty.io/wiki/native-transports.html">{@code
* netty_transport_native_unix}</a> is available.
*/
public static boolean isAvailable() {
return UNAVAILABILITY_CAUSE == null;
}
/**
* Ensure that <a href="https://netty.io/wiki/native-transports.html">{@code netty_transport_native_unix}</a> is
* available.
*
* @throws UnsatisfiedLinkError if unavailable
*/
public static void ensureAvailability() {
if (UNAVAILABILITY_CAUSE != null) {
throw (Error) new UnsatisfiedLinkError(
"failed to load the required native library").initCause(UNAVAILABILITY_CAUSE);
}
}
/**
* Returns the cause of unavailability of <a href="https://netty.io/wiki/native-transports.html">
* {@code netty_transport_native_unix}</a>.
*
* @return the cause if unavailable. {@code null} if available.
*/
public static Throwable unavailabilityCause() {
return UNAVAILABILITY_CAUSE;
}
private Unix() {
}
}