How do I load and use native library in java? - java

I've got a java class, calling a native method and trying to load library:
import java.io.UnsupportedEncodingException;
public class Main {
public static native String getMyString(String s);
/**
* #param args
* #throws UnsupportedEncodingException
*/
public static void main(String[] args) throws UnsupportedEncodingException {
// TODO Auto-generated method stub
// System.out.println("here!");
String s2 = getMyString("string text");
for (Byte b : s2.getBytes("UTF-8")) {
System.out.print(b);
System.out.print(",");
}
}
static {
System.loadLibrary("mylib.so");
}
}
The "mylib.so" is in the directory, where Main.class is located.
When I run java Main I get following exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no mylib.so in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1856)
at java.lang.Runtime.loadLibrary0(Runtime.java:845)
at java.lang.System.loadLibrary(System.java:1084)
at Main.<clinit>(Main.java:24)
What should I change for this to wark?
I've tried setting library full path without success

Do the following:
Use System.loadLibrary("mylib");
Copy mylib.so to libmylib.so
Run java -Djava.library.path=/root/ Main

"How to load native library"
public final class NativeLibsLoaderUtil {
private static final String JAVA_LIBRARY_PATH = "java.library.path";
private static final String SYS_PATHS = "sys_paths";
private NativeLibsLoaderUtil() {
}
private static void addLibsToJavaLibraryPath(final String tmpDirName) {
try {
System.setProperty(JAVA_LIBRARY_PATH, tmpDirName);
/* Optionally add these two lines */
System.setProperty("jna.library.path", tmpDirName);
System.setProperty("jni.library.path", tmpDirName);
final Field fieldSysPath = ClassLoader.class.getDeclaredField(SYS_PATHS);
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (IllegalAccessException | NoSuchFieldException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
Where tmpDirName is a directory where you store your library.
Or you can modify above class and use temp directory from your system property, like this:
/**
* Temporary directory system property name
*/
private static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
/**
*
* #return
*/
private static File getTempDir() {
final String tmpDirName = System.getProperty(JAVA_IO_TMPDIR);
final File tmpDir = new File(tmpDirName);
if (!tmpDir.exists()) {
tmpDir.mkdir();
}
return tmpDir;
}
!But first you have to copy there your native lib :)
Then to load native library call "addLibsToJavaLibraryPath" method in static block in "most root" class before any class constructor was executed.
static {
NativeLibsLoaderUtil.addLibsToJavaLibraryPath("/tmp");
}

You should add the so to library path:
-Djava.libarary.path= (this is in the java command).
if you run from eclipse:
How to add native library to "java.library.path" with Eclipse launch (instead of overriding it)

If you compiled opencv, on installation you should have seen something like:
make install:
-- Up-to-date: /usr/local/share/java/opencv4/libopencv_java460.so
-- Up-to-date: /usr/local/share/java/opencv4/opencv-460.jar
make a hard link to the /usr/lib/ folder:
$ sudo ln /usr/local/share/java/opencv4/libopencv_java460.so /usr/lib/libopencv_java460.so
And then just run:
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
that he will get the *.so

As Reimeus answered.
Or you can use
System.load("/Library/Path/libsample.so");

Related

How to set/get a value from another JVM

I have a class Normal with the following code:
public class Normal {
private static String myStr = "Not working...";
private static boolean running = true;
public static void main(String[] args) {
while(running) {
System.out.println(myStr);
}
}
}
And I have another class named Injector in another project. Its purpose is to change the values of Normal even though they are not in the same JVM:
public class Injector {
public static void main(String[] args) {
String PID = //Gets PID, which works fine
VirtualMachine vm = VirtualMachine.attach(PID);
/*
Set/Get field values for classes in vm?
*/
}
}
What I want to do is change the values myStr and running in the class Normal to "Working!" and false respectively without changing the code in Normal (Only in Injector).
Thanks in advance
You'll need two JARs:
One is Java Agent that uses Reflection to change the field value. Java Agent's main class should have agentmain entry point.
public static void agentmain(String args, Instrumentation instr) throws Exception {
Class normalClass = Class.forName("Normal");
Field myStrField = normalClass.getDeclaredField("myStr");
myStrField.setAccessible(true);
myStrField.set(null, "Working!");
}
You'll have to add MANIFEST.MF with Agent-Class attribute and pack the agent into a jar file.
The second one is a utility that uses Dynamic Attach to inject the agent jar into the running VM. Let pid be the target Java process ID.
import com.sun.tools.attach.VirtualMachine;
...
VirtualMachine vm = VirtualMachine.attach(pid);
try {
vm.loadAgent(agentJarPath, "");
} finally {
vm.detach();
}
A bit more details in the article.

Java Agent Development Framework - Eclipse and Maven integration

I created a maven project with JADE framework as a dependency but this framework requires different commands to execute the jar than ordinary java applications.
Build:
javac –classpath <JADE-classes> Class_name.java
Run:
java –classpath <JADE-classes> jade.Boot <agent-local-name>:<fully-qualified-agent-class>
Where <fully-qualified-agent-class> is package_name.Class_name
or
java –cp lib\jade.jar jade.Boot [options] [AgentSpecifierlist]
Is it possible to build a runnable jar using maven plugins so I just type java -jar myjar.jar instead of the command above?
Would mvn eclipse:eclipse command change build parameters of the eclipse project after editing the pom.xml file?
There isn't any such plugin available for JADE because it is not widely used framework and anyone hasn't bothered to develop a plugin for it. But there is a workaround to run it the conventional way, but this would only work if you already know your <fully-qualified-agent-class> names. what you can do is write a class that extends Thread and from that Thread's run() method invoke the JADE framework agent by passing the <fully-qualified-agent-class> as arguments. Refer to an example below.
jadeBootThread.java
public class jadeBootThread extends Thread {
private final String jadeBoot_CLASS_NAME = "jade.Boot";
private final String MAIN_METHOD_NAME = "main";
//add the <agent-local-name>:<fully-qualified-agent-class> name here;
// you can add more than one by semicolon separated values.
private final String ACTOR_NAMES_args = "Agent1:com.myagents.agent1";
private final String GUI_args = "-gui";
private final Class<?> secondClass;
private final Method main;
private final String[] params;
public jadeBootThread() throws ClassNotFoundException, SecurityException, NoSuchMethodException {
secondClass = Class.forName(jadeBoot_CLASS_NAME);
main = secondClass.getMethod(MAIN_METHOD_NAME, String[].class);
params = new String[]{GUI_args, ACTOR_NAMES_args};
}
#Override
public void run() {
try {
main.invoke(null, new Object[]{params});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
ex.printStacktrace();
}
}
}
Now you can invoke this thread from your main method or any other way by creating runnable jar file with eclipse plugin etc.
A better solution for this :
public class Example03 {
public static void main(String[] args){
String host;
int port;
String platform = null; //default name
boolean main = true;
host = "localhost";
port = -1; //default-port 1099
Runtime runtime = Runtime.instance();
Profile profile = null;
AgentContainer container = null;
profile = new ProfileImpl(host, port, platform, main);
// create container
container = runtime.createMainContainer(profile);
// create the agents
try {
AgentController agent1 = container.createNewAgent(
"Agent1",
routing.TransportAgent.class.getName(),
args);
AgentController agent2 = container.createNewAgent(
"Agent2",
routing.TransportAgent.class.getName(),
args);
// create the GUI
AgentController rma = container.createNewAgent("rma", "jade.tools.rma.rma", null);
// start the agents
agent1.start();
agent2.start();
rma.start();
} catch(StaleProxyException e) {
throw new RuntimeException(e);
}
}
}

Code does not give errors but does not give results either

I try to use Geoserver-Manager. I says:
package test;
import java.net.MalformedURLException;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
import it.geosolutions.geoserver.rest.GeoServerRESTReader;
public class RestTester
{
/**
* #param args
* #throws MalformedURLException
*/
public static void main(String[] args) throws MalformedURLException
{
System.out.println("fdfdfd");
// TODO Auto-generated method stub
String RESTURL = "http://localhost:8080/geoserver";
String RESTUSER = "admin";
String RESTPW = "geoserver";
GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
GeoServerRESTPublisher publisher = new GeoServerRESTPublisher(RESTURL, RESTUSER, RESTPW);
System.out.println("fdfdfd");
}
}
And there is something interesting. I start this application and get nothing in console. No any errors or my prints.
What can be wrong? I use Eclipse Galileo.
UPDATE
More info
Geoserver Manager add to application how java classes not *.jar files.
I delete all classes from project but RestTester. But still not get any prints in console.
UPDATE2
I delete RestTester class. And add new class HelloW.
public class HelloW
{
/**
* #param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
System.out.println("HelloW");
}
}
Run it and get error:
java.lang.NoClassDefFoundError: HelloW
Caused by: java.lang.ClassNotFoundException: HelloW
But when i create new project with same class all works fine. In project where i try Geoserver Manager i add some *.jar but its was only apache commons and jdom libraries, half of then i use in my another applications.

Eliminate hardcoded file paths and urls in web development

I'm currently developing a web site using servlets & spring framework. As usual it contains lots of files (jsp, js, css, images, various resources etc).
I'm trying to avoid writing any hardcoded path, or domain in any file ...
For example as you may know when a request is handled you 'forward' it to a jsp page (it's path probably will be hardcoded). Other examples are imports images/css/js etc in jsp files ...
Is there any general way (or tools) to avoid hardcoded paths/urls so any refactorings won't cause troubles?
EDIT
I use netbeans 7.1.2 ... Unfortunately netbeans only helps with pure java code. When working with jsp files things are limited, and if you add custom tag files and Jsp 2.0 EL is like programming in console mode :p
In the JSP files themselves, you can avoid nearly all hardcoded domain / urls by using JSTL
For example, when creating a link to another page, you would do it like this:
Refer an Entrepreneur!
This means that, regardless of where your webapp is, the link will always have the right url. For example, in my development box this link would be:
http://localhost:8080/accounts/referrals/send.html
But on my production server, it resolves correctly to:
http://wwww.mydomain.com/referrals/send.html
You can see that in my dev server, the webapp context is under /accounts, but on the production machine, it's just under / as the webapp is under the root context.
You can read a small tutorial here
Properties file is always a good option so that you have to make changes if any only at one point.
If you are referencing any static contents (js, images, css, etc), you don't have to hardcode the entire file path. Instead, you can do this:-
<img src="${pageContext.request.contextPath}/resources/images/test.jpg"/>
The rest of the file paths (Hibernate domain mappings, forwarded page in Spring controller, etc) should be relative to your project structure, and most IDEs are smart enough to refactor them without problem... or at least in my case, IntelliJ seems to handle of all that for me.
At some point of time, you need to ask yourself, how much of hardcoding is acceptable vs not acceptable? Further, I wouldn't try to stray too far away from the Spring/Hibernate recommended solutions. If you make everything too abstract, you have a different set of problem to deal with and it becomes counterproductive to other peers that may be inheriting your project in the future.
Actually I just came up with an idea. Since netbeans does analysis and shows dependencies on java code, maybe it's better to handle all paths & domains as java variables.
I've created a package on my project named FileResolver and inside I have one class for each file type on my project (eg one class for Jsp files, one for Css files etc). Inside those files I'll record & hardcode all paths of all files in public static final String variables. Sample:
public class Jsps {
public class layouts{
public static final String main = "layouts/main.jsp";
}
public class pages{
public static final String error = "pages/error.jsp";
public static final String login = "pages/login.jsp";
public static final String register = "pages/register.jsp";
}
...
}
All over my project I should use the variables instead of paths. Then anytime I refactor a file, I'll have only one file to change is the mapping value in those variables ...
And if somethime I need to change the variable, netbeans will refactor all of them in the project at once ...
I think this will work just fine since I keep my project clean from file paths and the only thing I have to worry about is the mapping in that file of the variables to appropriate file paths.
EDIT
I'll write a simple parser to create those java files instead of writting by hand for all files ... I'll update when I finish it
UPDATE
Here is my FileResolverGenerator
public class FileResolverGenerator {
private static final String newFilePath = "C:/Users/Foo/Desktop/Jsps.java";
private static final String scanRootFolder = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp";
private static final String varValueReplaceSource = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
private static final String varValueReplaceTarget = "";
private static final boolean valueAlign = true;
private static final int varNameSpaces = 15;
public static void main(String[] args){
try {
// Create file and a writer
File f = new File(newFilePath);
f.createNewFile();
bw = new BufferedWriter( new FileWriter(f) );
// Execute
filesParser( new File(scanRootFolder) );
// 'Burn' file
bw.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesParser(File rootFolder) throws FileNotFoundException, IOException{
folderIn(rootFolder);
// Files first
if(!rootFolder.exists()) throw new FileNotFoundException();
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ continue; }
else if(f.isFile()){ writeFileVariable(f); }
}
// Folders next
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ filesParser(f); }
else if(f.isFile()){ continue; }
}
folderOut(rootFolder);
}
// ================================================================================================ //
// ============================================ PRINTS ============================================ //
// ================================================================================================ //
private static BufferedWriter bw;
private static int tabCount = 0;
private static void folderIn(File f) throws IOException{
bw.append("\n\n");
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("public class "+f.getName()+"{\n");
tabCount++;
}
private static void folderOut(File f) throws IOException{
tabCount--;
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("}\n");
}
private static void writeFileVariable(File f) throws IOException{
String varName = f.getName().split("\\.")[0].replaceAll("-", "");
String varValue = f.getPath().replaceAll("\\\\","/")
.replace(varValueReplaceSource.replaceAll("\\\\","/"),varValueReplaceTarget.replaceAll("\\\\","/"));
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("public static final String "+varName+" = ");
if(valueAlign){
for(int i=0; i<varNameSpaces-varName.length(); i++) bw.append(" ");
bw.append("\t"); }
bw.append("\""+varValue+"\";\n");
}
}
Just to be specific ... This scans all files under "/WEB-INF/jsp/" and creates a java file having all jsp files 'registered' to public static final String variables with each path ... The idea is to use the generated java file as reference for all jsps are in project ... always use these variables instead of hardcoded paths ..
This has nothing to do with the project or any project. It's just a tool which saves you
time, instead of doing this by hand for every file in the project.
I also created another class ResolverConsistencyChecker, which takes all variables and checks if the filepath is correct (file exists) ... since we didn't made any changes to filenames and filepaths all tests are passed.
This method should run when testing project for 'errors'
public class ResolverConsistencyChecker {
private static Class checkClass = Jsps.class;
private static String fullPathPrefix = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
public static void main(String[] args){
try {
filesChecker( checkClass );
System.out.println( "Tests passed. All files locations are valid" );
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesChecker(Class rootClass) throws FileNotFoundException, IOException{
// Check file paths in current class depth
for(Field f : rootClass.getFields()){
try {
String fullFilePath = fullPathPrefix+f.get(f.getName()).toString();
File file = new File( fullFilePath );
if( !file.exists() )
throw new FileNotFoundException("Variable: '"+f.getName()+"'\nFile "+fullFilePath);
} catch (IllegalArgumentException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Check for embedded classes
for(Class c : rootClass.getClasses()){
filesChecker(c);
}
}
}

"Hello World" with Java annotations

Problem description: Compile 2 jar files independently, without having to include each other on classpath; and at runtime, include both and invoke main() in one jar to print a string on stdout. Parts of the output string have to come from the 2nd jar.
Constraints: The solution cannot be IDE-dependent or use any other jar files.
Answering what have I done so far: My Solution is described below.
Reason to ask the question: I am trying to figure out if/how to use annotations to solve this problem (hopefully in a more elegant manner), but cannot find any suitable documentation or tutorial. I appreciate any pointer(s) for that also.
My Solution: A batch file (on Unix, please change the backslash to forward slash, semicolon to colon and the rem's to #) as follows:
rem Compile and package the testing class (Main) without any library
javac -d target core\*.java
cd target
jar cvf ..\main.jar .\core
cd ..
rem Compile and package the Greeting and Greeted classes as a library
javac -d lib impl\*.java
cd lib
jar cvf ..\mylib.jar .\impl
cd ..
rem Use the two parts above at runtime and execute main() in Main class
java -cp main.jar;mylib.jar core.Main
There are 2 files in the impl directory and 2 in the core, as follows:
/* File: impl/Greeting.java */
package impl;
public class Greeting {
public String getGreeting () {
return "Hello";
}}
/* File: impl/Greeted.java */
package impl;
public class Greeted {
public String getGreeted () {
return "world";
}
/* File: core/Main.java */
package core;
public class Main {
private String greeting = "Learn annotations", greeted = "keep using Java",
// Can read the following 4 values from a configuration file, too
// Trying to see if we can get these using Java annotations
greetingClassName = "impl.Greeting", greetingMethod = "getGreeting",
greetedClassName = "impl.Greeted", greetedMethod = "getGreeted";
public Main () {
try {
MyRunTime runTime = new MyRunTime();
Object gting = runTime.getInstance(greetingClassName),
gted = runTime.getInstance(greetedClassName),
g1Str = runTime.getResponseNoArg (gting, greetingMethod),
g2Str = runTime.getResponseNoArg (gted, greetedMethod);
if (g1Str instanceof String) greeting = (String) g1Str;
if (g2Str instanceof String) greeted = (String) g2Str;
} catch (Exception ex) {
System.err.println ("Error in Library loading: " + ex.getMessage());
}}
public void greet () {
System.out.println (greeting + ", " + greeted + "!");
}
public static void main (String[] args) {
new Main().greet();
}}
/* File: core/MyRunTime.java */
package core;
import java.lang.reflect.*;
public class MyRunTime {
public Object getResponseNoArg (Object anInstance, String methodName) throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
Method method = anInstance.getClass().getMethod (methodName);
return method.invoke (anInstance);
}
public Object getInstance (String className) throws
ClassNotFoundException,
InstantiationException,
IllegalAccessException {
Class c = Class.forName (className);
return c.newInstance();
}
}
That's it. I would also like not to mess with the ClassLoader unless absolutely necessary. Once I get a handle on how to do this with annotations, I can look into passing arguments and go forward. Thank you for your help.
I wouldn't use Annotations for this - it's probably worth covering what Annotations are and where they are best used.
Instead I would do something like:
Place different files in each jar
A main class to each jar file, which does the same thing: list the files on the classpath
I think that would meet the project requirements.
To list the files on the classpath you could so something like:
public class Main {
public static void main(final String[] args) throws java.lang.Throwable {
final String list = System.getProperty( "java.class.path" );
for (String path : list.split( ";" )) {
java.io.File object = new java.io.File( path );
if ( object.isDirectory() )
for ( String entry : object.list() ) {
java.io.File thing = new java.io.File( entry );
if ( thing.isFile() )
System.out.println( thing );
else if( object.isFile() )
System.out.println( object );
}
}
}
}

Categories