Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ if [ -n "$ARTEMIS_SHELL_HISTORY" ]; then
SHELL_HISTORY_ARG="-Dartemis.shell.history=${ARTEMIS_SHELL_HISTORY}"
fi

# Netty 4.2 only uses sun.misc.Unsafe on JDK 24+ when it's explicitly permitted; the NIO/MAPPED journals
# rely on it, so enable it there to avoid a broker startup failure. The option is unrecognized before JDK 23,
# so it's only added when recognized.
$JAVACMD --sun-misc-unsafe-memory-access=allow --version > /dev/null 2>&1 && ALLOW_UNSAFE="--sun-misc-unsafe-memory-access=allow"

exec "$JAVACMD" \
$LOGGING_ARGS \
$JAVA_ARGS \
Expand All @@ -138,6 +143,7 @@ exec "$JAVACMD" \
-Ddata.dir="$ARTEMIS_DATA_DIR" \
-Dartemis.instance.etc="$ARTEMIS_INSTANCE_ETC" \
$SHELL_HISTORY_ARG \
$ALLOW_UNSAFE \
$DEBUG_ARGS \
$JAVA_ARGS_APPEND \
org.apache.activemq.artemis.boot.Artemis "$@"
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ move /Y %ARTEMIS_OOME_DUMP% %ARTEMIS_OOME_DUMP%.bkp
rem "Create full JVM Args"
set JVM_ARGS=%LOGGING_ARGS%
set JVM_ARGS=%JVM_ARGS% %JAVA_ARGS%

rem "Netty 4.2 only uses sun.misc.Unsafe on JDK 24+ when it's explicitly permitted; the NIO/MAPPED journals"
rem "rely on it, so enable it there to avoid a broker startup failure. The option is unrecognized before JDK 23,"
rem "so it's only added when recognized."
"%_JAVACMD%" --sun-misc-unsafe-memory-access=allow --version >nul 2>&1 && set JVM_ARGS=%JVM_ARGS% --sun-misc-unsafe-memory-access=allow
if not "%ARTEMIS_CLUSTER_PROPS%"=="" set JVM_ARGS=%JVM_ARGS% %ARTEMIS_CLUSTER_PROPS%
set JVM_ARGS=%JVM_ARGS% -classpath %ARTEMIS_HOME%\lib\artemis-boot.jar
set JVM_ARGS=%JVM_ARGS% -Dartemis.home=%ARTEMIS_HOME%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ if [ -z "$LOGGING_ARGS" ]; then
fi

if [ -z "$JAVA_ARGS" ]; then
JAVA_ARGS="-Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED ${java-utility-opts}"
JAVA_ARGS="-Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --enable-native-access=ALL-UNNAMED ${java-utility-opts}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least its the case that --enable-native-access was already in JDK17 (as the initial FFM in 17 was an incubator addition there) so hopefully that means it works on all versions of JDK17+ as opposed to just post-GA backport releases, save us doing any checking.

fi

# Uncomment to enable remote debugging
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ set ARTEMIS_DATA_DIR="${artemis.instance.data}"

IF "%LOGGING_ARGS%"=="" (set LOGGING_ARGS=-Dlog4j2.configurationFile=log4j2-utility.properties)

IF "%JAVA_ARGS%"=="" (set JAVA_ARGS=-Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED ${java-utility-opts})
IF "%JAVA_ARGS%"=="" (set JAVA_ARGS=-Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --enable-native-access=ALL-UNNAMED ${java-utility-opts})

rem Uncomment to enable remote debugging
rem set DEBUG_ARGS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ HAWTIO_ROLES='${role}'

# Java Opts
if [ -z "$JAVA_ARGS" ]; then
JAVA_ARGS="-XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx${java-memory} -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Dhawtio.http.strictTransportSecurity=max-age=31536000;includeSubDomains;preload -Djolokia.policyLocation=classpath:jolokia-access.xml -Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED ${java-opts}"
JAVA_ARGS="-XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx${java-memory} -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Dhawtio.http.strictTransportSecurity=max-age=31536000;includeSubDomains;preload -Djolokia.policyLocation=classpath:jolokia-access.xml -Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --enable-native-access=ALL-UNNAMED ${java-opts}"
fi

# Uncomment to enable logging for Safepoint JVM pauses
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ rem Cluster Properties: Used to pass arguments to Apache Artemis which can be re
rem set ARTEMIS_CLUSTER_PROPS=-Dactivemq.remoting.default.port=61617 -Dactivemq.remoting.amqp.port=5673 -Dactivemq.remoting.stomp.port=61614 -Dactivemq.remoting.hornetq.port=5446

rem Java Opts
IF "%JAVA_ARGS%"=="" (set JAVA_ARGS=-XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx${java-memory} -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Dhawtio.http.strictTransportSecurity=max-age=31536000;includeSubDomains;preload -Djolokia.policyLocation=classpath:jolokia-access.xml -Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dhawtio.roles=${role} ${java-opts} )
IF "%JAVA_ARGS%"=="" (set JAVA_ARGS=-XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx${java-memory} -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Dhawtio.http.strictTransportSecurity=max-age=31536000;includeSubDomains;preload -Djolokia.policyLocation=classpath:jolokia-access.xml -Dlog4j2.disableJmx=true --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --enable-native-access=ALL-UNNAMED -Dhawtio.roles=${role} ${java-opts} )

rem Logs Safepoints JVM pauses: Uncomment to enable them
rem In addition to the traditional GC logs you could enable some JVM flags to know any meaningful and "hidden" pause that could
Expand Down
19 changes: 19 additions & 0 deletions artemis-commons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-epoll</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-kqueue</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-io_uring</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-io_uring</artifactId>
<classifier>${netty-transport-native-io_uring-classifier}</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,22 @@ public interface ActiveMQUtilLogger {

@LogMessage(id = 202017, value = "Algorithm two-way is deprecated and will be removed from the default codec in a future version. Use a custom codec instead. Consult the manual for details.", level = LogMessage.Level.WARN)
void deprecatedDefaultCodecTwoWayAlgorithm();

@LogMessage(id = 202018, value = "Unable to check KQueue availability ", level = LogMessage.Level.WARN)
void unableToCheckKQueueAvailability(Throwable e);

@LogMessage(id = 202019, value = "KQueue is not available, please add to the classpath or configure useKQueue=false to remove this warning", level = LogMessage.Level.WARN)
void unableToCheckKQueueAvailabilityNoClass();

@LogMessage(id = 202020, value = "Unable to check Epoll availability ", level = LogMessage.Level.WARN)
void unableToCheckEpollAvailability(Throwable e);

@LogMessage(id = 202021, value = "Epoll is not available, please add to the classpath or configure useEpoll=false to remove this warning", level = LogMessage.Level.WARN)
void unableToCheckEpollAvailabilityNoClass();

@LogMessage(id = 202022, value = "Unable to check IoUring availability ", level = LogMessage.Level.WARN)
void unableToCheckIoUringAvailability(Throwable e);

@LogMessage(id = 202023, value = "IoUring is not available, please add to the classpath or configure useIoUring=false to remove this warning", level = LogMessage.Level.WARN)
void unableToCheckIoUringAvailabilityNoClass();
}
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,11 @@ private static void uncheckedZeros(final ByteBuffer buffer, int offset, int byte
Arrays.fill(buffer.array(), start, start + bytes, zero);
} else {
//slow path
// absolute put() checks index against limit, but we zero up to capacity
final ByteBuffer dup = buffer.duplicate();
dup.clear();
for (int i = 0; i < bytes; i++) {
buffer.put(i + offset, zero);
dup.put(i + offset, zero);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.activemq.artemis.core.remoting.impl.netty;
package org.apache.activemq.artemis.utils;

import io.netty.channel.epoll.Epoll;
import io.netty.channel.kqueue.KQueue;
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
import org.apache.activemq.artemis.utils.Env;
import org.apache.activemq.artemis.logs.ActiveMQUtilLogger;

/**
* This class will check for Epoll or KQueue is available, and return false in case of NoClassDefFoundError it could be
* improved to check for other cases eventually.
* This class will check if certain dependencies are available, and return false in case of NoClassDefFoundError
*/
public class CheckDependencies {

public static final boolean isEpollAvailable() {
try {
return Env.isLinuxOs() && Epoll.isAvailable();
} catch (NoClassDefFoundError noClassDefFoundError) {
ActiveMQClientLogger.LOGGER.unableToCheckEpollAvailabilitynoClass();
ActiveMQUtilLogger.LOGGER.unableToCheckEpollAvailabilityNoClass();
return false;
} catch (Throwable e) {
ActiveMQClientLogger.LOGGER.unableToCheckEpollAvailability(e);
ActiveMQUtilLogger.LOGGER.unableToCheckEpollAvailability(e);
return false;
}
}
Expand All @@ -44,10 +41,22 @@ public static final boolean isKQueueAvailable() {
try {
return Env.isMacOs() && KQueue.isAvailable();
} catch (NoClassDefFoundError noClassDefFoundError) {
ActiveMQClientLogger.LOGGER.unableToCheckKQueueAvailabilityNoClass();
ActiveMQUtilLogger.LOGGER.unableToCheckKQueueAvailabilityNoClass();
return false;
} catch (Throwable e) {
ActiveMQUtilLogger.LOGGER.unableToCheckKQueueAvailability(e);
return false;
}
}

public static final boolean isIoUringAvailable() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added via netty/netty#15785 a way to verify the status of the different optimizations made by io_uring on the OS - you can use it for reporting/debugging 👍

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was about to use it, but I see now that it's so recent that it's not in a release yet. 😆

try {
return Env.isLinuxOs() && NettyIoUringSupport.isAvailable();
} catch (NoClassDefFoundError noClassDefFoundError) {
ActiveMQUtilLogger.LOGGER.unableToCheckIoUringAvailabilityNoClass();
return false;
} catch (Throwable e) {
ActiveMQClientLogger.LOGGER.unableToCheckKQueueAvailability(e);
ActiveMQUtilLogger.LOGGER.unableToCheckIoUringAvailability(e);
return false;
}
}
Comment thread
jbertram marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
*
* http://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 org.apache.activemq.artemis.utils;

import io.netty.channel.Channel;
import io.netty.channel.IoHandlerFactory;
import io.netty.channel.ServerChannel;
import io.netty.channel.uring.IoUring;
import io.netty.channel.uring.IoUringIoHandler;
import io.netty.channel.uring.IoUringServerSocketChannel;
import io.netty.channel.uring.IoUringSocketChannel;

public final class NettyIoUringSupport {

public static boolean isAvailable() {
return IoUring.isAvailable();
}

public static IoHandlerFactory newHandlerFactory() {
return IoUringIoHandler.newFactory();
}

public static Class<? extends Channel> socketChannelClass() {
return IoUringSocketChannel.class;
}

public static Class<? extends ServerChannel> serverSocketChannelClass() {
return IoUringServerSocketChannel.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,12 @@ public static Process spawnVM(String classPath,
commandList.add(jacocoAgent);
}

if (Runtime.version().feature() >= 24) {
commandList.add("--enable-native-access=ALL-UNNAMED");
// the NIO/MAPPED journals rely on unsafe
commandList.add("--sun-misc-unsafe-memory-access=allow");
}

commandList.add(className);
for (String arg : args) {
commandList.add(arg);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
*
* http://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 org.apache.activemq.artemis.utils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

import org.junit.jupiter.api.Test;

/**
* Sanity checks for {@link NettyIoUringSupport}, the single class that references the Netty io_uring transport types.
* The io_uring classes are on this module's (optional) test classpath, so the class-level assertions below always run;
* the native-availability assertion is guarded because it needs a supported Linux platform with the native lib loaded.
*/
public class NettyIoUringSupportTest {

@Test
public void testChannelClassesAreIoUringTypes() {
assertEquals("io.netty.channel.uring.IoUringSocketChannel", NettyIoUringSupport.socketChannelClass().getName());
assertEquals("io.netty.channel.uring.IoUringServerSocketChannel", NettyIoUringSupport.serverSocketChannelClass().getName());
}

@Test
public void testAvailabilityCheckDoesNotThrow() {
// this must always return cleanly (true or false); it must never propagate an exception, since callers rely on it
// as the gate before touching any io_uring type
boolean available = CheckDependencies.isIoUringAvailable();

// when Env reports a non-Linux platform io_uring can never be considered available
if (!Env.isLinuxOs()) {
assertEquals(false, available);
}
}

@Test
public void testHandlerFactoryWhenAvailable() {
assumeTrue(CheckDependencies.isIoUringAvailable());

// on a platform where io_uring is available the isolated factory/channel accessors must produce usable objects
assertNotNull(NettyIoUringSupport.newHandlerFactory());
assertNotNull(NettyIoUringSupport.socketChannelClass());
assertNotNull(NettyIoUringSupport.serverSocketChannelClass());
}
}
2 changes: 1 addition & 1 deletion artemis-core-client-osgi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
<Import-Package>
org.glassfish.json*;resolution:=optional,
de.dentrassi.crypto.pem;resolution:=optional,
io.netty.buffer;io.netty.*;version="[4.1,5)",
io.netty.*;version="[4.2,5)",
*
</Import-Package>
<_exportcontents>org.apache.activemq.artemis.*;-noimport:=true</_exportcontents>
Expand Down
7 changes: 3 additions & 4 deletions artemis-core-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-kqueue</artifactId>
</dependency>
<!-- io_uring is off by default and its Netty deps are intentionally omitted here so they aren't pulled in
transitively or bundled. Users who want io_uring add netty-transport-classes-io_uring and
netty-transport-native-io_uring themselves; see NettyIoUringSupport / CheckDependencies.isIoUringAvailable(). -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
Expand All @@ -109,10 +112,6 @@
<groupId>io.netty</groupId>
<artifactId>netty-handler-proxy</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-socks</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/**
* Logger Codes 210000 - 218999
*/
@LogBundle(projectCode = "AMQ", regexID = "21[0-8][0-9]{3}", retiredIDs = {211001, 211002, 211003, 212000, 212006, 212029, 212074, 212078, 214012, 214023, 214024, 214026, 214027, 214028, 214029})
@LogBundle(projectCode = "AMQ", regexID = "21[0-8][0-9]{3}", retiredIDs = {211001, 211002, 211003, 212000, 212006, 212029, 212071, 212073, 212074, 212075, 212076, 212078, 214012, 214023, 214024, 214026, 214027, 214028, 214029})
public interface ActiveMQClientLogger {

ActiveMQClientLogger LOGGER = BundleFactory.newBundle(ActiveMQClientLogger.class, ActiveMQClientLogger.class.getPackage().getName());
Expand Down Expand Up @@ -236,21 +236,9 @@ public interface ActiveMQClientLogger {
@LogMessage(id = 212070, value = "Unable to initialize VersionLoader ", level = LogMessage.Level.WARN)
void unableToInitVersionLoader(Throwable e);

@LogMessage(id = 212071, value = "Unable to check Epoll availability ", level = LogMessage.Level.WARN)
void unableToCheckEpollAvailability(Throwable e);

@LogMessage(id = 212072, value = "Failed to change channel state to ReadyForWriting ", level = LogMessage.Level.WARN)
void failedToSetChannelReadyForWriting(Throwable e);

@LogMessage(id = 212073, value = "Unable to check KQueue availability ", level = LogMessage.Level.WARN)
void unableToCheckKQueueAvailability(Throwable e);

@LogMessage(id = 212075, value = "KQueue is not available, please add to the classpath or configure useKQueue=false to remove this warning", level = LogMessage.Level.WARN)
void unableToCheckKQueueAvailabilityNoClass();

@LogMessage(id = 212076, value = "Epoll is not available, please add to the classpath or configure useEpoll=false to remove this warning", level = LogMessage.Level.WARN)
void unableToCheckEpollAvailabilitynoClass();

@LogMessage(id = 212077, value = "Timed out waiting to receive initial broadcast from cluster. Retry {} of {}", level = LogMessage.Level.WARN)
void broadcastTimeout(int retry, int maxretry);

Expand Down
Loading
Loading