skip to Main Content

I am running ActiveMQ Artemis (2.18.0) on CentOS

OS: CentOS Linux release 7.9.2009 (Core)
Kernel: Linux 3.10.0-1160.31.1.el7.x86_64

Since I am running a kernel version newer than 2.6 on an x86_64 architecture then based on the documentation I only need to ensure that libaio is installed:

yum install libaio
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.1000mbps.com
 * centos-sclo-rh: mirror.seedvps.com
 * centos-sclo-sclo: mirror.seedvps.com
 * extras: mirror.seedvps.com
 * updates: mirror.seedvps.com
Package libaio-0.3.109-13.el7.x86_64 already installed and latest version

In the broker.xml I set the journal type to AIO:

<journal-type>ASYNCIO</journal-type>

I start the broker programmatically:

broker = new EmbeddedActiveMQ(); 
broker.setConfigResourcePath(fileConfig);
broker.start();

However, I get the following warning:

org.apache.activemq.artemis.core.server : AMQ222018: AIO was not located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal

What could be the case?

2

Answers


  1. Chosen as BEST ANSWER

    The warning occurs because in order to integrate properly with AIO three conditions must be met:

    1. Run on Linux.
    2. LibAIO must be installed.
    3. The java.library.path Java system property must be set to the directory with the proper shared object (e.g. libartemis-native-64.so).

    In this case the third condition isn't met. Normally java.library.path is set on startup by the bin/artemis script, but this isn't done when embedding ActiveMQ Artemis into a Java application.

    If using EmbeddedActiveMQ you can add AIO support in one of the following ways:

    Manually

    1. Download the Artemis version (i.e. the same version as your ActiveMQ Artemis Maven dependency).
    2. Unzip the downloaded version (e.g. apache-artemis-2.18.0-bin.zip).
    3. Copy the library proper library for your platform architecture (e.g. from apache-artemis-2.18.0/bin/lib/linux-x86_64).
    4. Put the library on every Linux server where the broker is running.
    5. Start your application with the following command:
      -Djava.library.path="/path/to/linux-x86_64/"
      

    Docker Container

    Add the library to the container and startup java with the -Djava.library.path parameter.

    Programmatically

    If you feel comfortably (this works for me) you can load the library in runtime:

        File aioFile = new File("./linux-x86_64/libartemis-native-64.so");
    
            if(OSUtil.getOS().equals(OSUtil.OS.LINUX)){
    
                if(!aioFile.exists()) {
    
                    //Create an empty file
                    FileUtils.touch(aioFile);
    
                    //Copy file from resources into empty file
                    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
                    InputStream is = classloader.getResourceAsStream("libartemis-native-64.so");
                    Files.copy(is, aioFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                    is.close();
    
                    logger.info("AIO Directory is set to " + aioFile.getParent());
    
                }
    
                addDir(aioFile.getParent());
    
            }
    
        public static void addDir(String s) throws IOException {
            try {
                // This enables the java.library.path to be modified at runtime
                // From a Sun engineer at http://forums.sun.com/thread.jspa?threadID=707176
                //
                Field field = ClassLoader.class.getDeclaredField("usr_paths");
                field.setAccessible(true);
                String[] paths = (String[])field.get(null);
                for (int i = 0; i < paths.length; i++) {
                    if (s.equals(paths[i])) {
                        return;
                    }
                }
                String[] tmp = new String[paths.length+1];
                System.arraycopy(paths,0,tmp,0,paths.length);
                tmp[paths.length] = s;
                field.set(null,tmp);
                System.setProperty("java.library.path", System.getProperty("java.library.path") + File.pathSeparator + s);
            } catch (IllegalAccessException e) {
                throw new IOException("Failed to get permissions to set library path");
            } catch (NoSuchFieldException e) {
                throw new IOException("Failed to get field handle to set library path");
            }
        }
    
    

    For more info on loading java.library.path at runtime see this SO article.


  2. By starting the broker yourself programmatically you miss an important configuration detail performed by the artemis run command which sets the java.library.path system property to include the proper JNI library for AIO integration. Therefore you’ll need to do this manually when you start your own Java application which starts the embedded instance of ActiveMQ Artemis. The library you need is in $ARTEMIS_HOME/bin/lib/linux-x86_64.

    The documentation you cited references this fact saying:

    These are the native libraries distributed by Apache ActiveMQ Artemis:

    • libartemis-native-64.so – x86 64 bits
    • We distributed a 32-bit version until early 2017. While it’s not available on the distribution any longer it should still be possible to compile to a 32-bit environment if needed.

    When using libaio, Apache ActiveMQ Artemis will always try loading these files as long as they are on the library path

    If you then follow the library path link you’ll see this:

    If you’re using the Asynchronous IO Journal on Linux, you need to specify java.library.path as a property on your Java options. This is done automatically in the scripts.

    If you don’t specify java.library.path at your Java options then the JVM will use the environment variable LD_LIBRARY_PATH.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search