0

I am using Tomcat7 and Ubuntu. I have a Java web application which uses some native libraries. When I run the web application within Eclipse it works through Eclipse internal Tomcat server during debugging. However, when I deploy the applcation to a hosted Tomcat service, the application fails when it reaches the point of loading these libraries.

  1. I put the native libraries in /home/me/my_shared_libs, and gave
    folder and file ownership to user "Tomcat7" -- sudo chown
  2. I give all permissions of the native libraries to "Tomcat7" user -- sudo chmod
  3. In do sudo vi /usr/share/tomcat7/bin/setenv.sh, and put the following in the file export CATALINA_OPTS="-Djava.library.path=/home/me/my_shared_libs"
  4. Then I restart Tomcat -- sudo service tomcat7 restart And, whenever refernce to load native libraries is reached, I get an error about InvocationTargetException.

I am also open to the option of adding the native libraries as part of the the application's .WAR file. (Although I am not sure how to do this in Eclipse).

Log of /var/log/tomcat7/catalina.out-->

Jun 30, 2016 8:11:50 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3643 ms
Load my_native_lib_called. libmachoman.so: cannot open shared object file: No such file or directory

EDIT: I found out something very interesting. Tomcat does pick up the library location that I set above. What happens is I have two types of libraries (.so) files in the location. The first library (libcore.so) calls/loads the the second library (libmachoman.so). libcore.so is found and loaded both libmachoman.so is not, even though both are in the same location.

nikk
  • 2,627
  • 5
  • 30
  • 51
  • 1
    Can you see the library path set in the startup logs ? – 11thdimension Jun 30 '16 at 19:02
  • @11thdimension thank you. No I do NOT see that Tomcat picked up the path I set above. Thanks for this new knowledge. How can I ensure that it does? I just added the log of tomcat to question. – nikk Jun 30 '16 at 19:22
  • In the question title you have mentioned that tomcat is running as a service. You can find the script which creates the service and parameters for the Tomcat can be added there. – 11thdimension Jun 30 '16 at 19:30
  • @11thdimension that sounds like a tough solution especially since I am deploying multiple systems not just one server. I will rather have an application-specific solution than change system settings. Exporting the native libs as part of the .war file work for me, but I am not sure how to do that. – nikk Jun 30 '16 at 19:36
  • 1
    can you try not having them under a /home/* directory. just in case the /home/ is giving weird results. – SnakeDoc Jun 30 '16 at 19:44

2 Answers2

1

It can be done from the code itself. That should give you confidence in the loading of the library.

To do this you can use System.load()

It takes absolute path of the library for example

System.load("/PATH/TO/.so");

Run this piece of code one once when the application starts up before calling the library functions.

You'll have to place your library in a custom location on all the servers.

System.loadLibrary() is also used for the same purpose but the difference is that it would load library by name and would look into locations specified by the Java environment variable java.library.path.

But that can be a pain to set as you have mentioned, this change would have to be done in all the instances of tomcat.

11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • I looked further, and see that the library location may not be problem, at least for the first library -- which then calls a secondary library. The first library is a wrapper around the second. The first was found and loaded therefore no error in catalina.out file, but the second library can't be found whenever the first library reaches the point where it loads it. This is strange because the application works well as standalone. Updated question. – nikk Jun 30 '16 at 20:48
  • In the standalone version print the `System.getProperty("java.library.path"`) and then print the same in the web application, compare the values printed this might give a clue. – 11thdimension Jul 01 '16 at 15:48
  • In the Java app, I load the initial library using `System.loadLibrary("lib_mymainlib.so")`, and the second library is loaded in native code as `dlopen("lib_mynative_lib.so", 1)`. I wonder if that makes a difference. I will try adding the debug messages as advised. – nikk Jul 01 '16 at 17:03
  • May be calling `System.loadLibrary()` for `lib_mynative_lib.so` also would make a difference. – 11thdimension Jul 01 '16 at 17:32
0

After days of headache, I have a solution.

  1. Edit file

    sudo vi /etc/ld.so.conf

  2. Append the location of native libs in file

    include /etc/ld.so.conf.d/*.conf /home/me/my_shared_lib

  3. load config

    sudo ldconfig

  4. View the new change

    ldconfig -p | grep my_shared_lib

This tells the dynamic linker where to look for native libraries.

My problem is solved.

There are other alternative solutions here, which may or may not have some cons.

Alternatively (also found out), you can can export LD_LIBRARY_PATH in the setenv.sh file under /usr/share/tomcat7/bin/ instead of the above steps. Settings become part of Tomcat; cleaner approach.

nikk
  • 2,627
  • 5
  • 30
  • 51