Java JNI Interface: Native functions relative file paths - java

I am having problems with relative file paths that native functions use. When I call native C function from Java code, I get segmentation fault due to null file pointer. The only thing that works is to change these paths into absolute file paths, which is not solution for me. Is there any way to set root directory for native functions or to use Java project root folder to navigate through directories, or the absolute path is the only way?

Java does not have a way to change the working directory.
This is because the Java developers consider changing the working directory to create more problems than it solves. specifically:
It would be global mutable state. Global mutable state makes it harder to isolate parts of the application from each other.
It would be prone to race conditions (another side effect of being global mutable state).
It would not have a significant benefit. Everything that you could do by changing the current directory you can already do with absolute paths.
Your C code will need to use absolute paths.
Alternatively, if you are willing to write additional C code, your C code could call the operating system's chdir function directly. This may be dangerous, as the JVM is not designed for this possibility.

I solved the problem! Solution is using File.getAbsoluteFilePath() function, and passing it to native C function. It can be used for finding absolute path of shared library also, which makes application platform independent. C code can navigate through it's directories like before bounding with Java code.

Do you work in Linux?
in Linux,you can add the path
$LD_LIBRARY_PATH=.so file path
to the ~/.bashrcfile and then reboot..
If you work with windows, you can put the .dll file in the path that as the .class file path.

Related

How does java.* libraries implement the Java native interface to use native methods and it's functionalities?

I wonder how java.* libraries implement the java native interface?
To be more specific I am investigating the java.awt.Robot and come across native method calls. As I am in windows - does that mean there is a .cpp file laying around somewhere (inside the java.awt.* package?) - that the java.awt.Robot uses?
Whenever you call native code, you have to go via JNI. Typically, you need to build shared library. Calling schema follows (note that you don't call C file - it's just visualization of which method will be called):
So, in a sense, there is a file that contains source code of the library that you call.
In case of Windows, shared libraries are DLL files in case of Linux they are typically so files and in macOS dylib. If you want to make them "visible" to your Java code, you have few options here. You can put location (directory where library is) in:
PATH (windows)
LD_LIBRARY_PATH (macOS/Linux)
-Djava.library.path - work for all systems, it's just a jvm's argument.

Using the "file:" prefix to file paths in Java filename strings?

Getting resources for Java projects has always been fairly confusing to me, as the documentation doesn't explain it very well in my opinion, and I end up having to re-learn it every time I need to use it in a project. Most recently, using JavaFX, I was trying to load an image. The constructor requires a string representing the file path. I had come up with a very hacky method of doing this in the past, but I recently came across this StackOverflow post, and the accepted answer shows a very simple way of referencing the top level of the Eclipse project so that I can access source folders in the build path and easily locate my image files.
Is there a name for this particular delimeter? Are there other delimeters like it? Would there be problems using this notation when running this code in an executable JAR?
Any information would be greatly appreciated. And if this isn't the best way to approach this and someone could give me an adequate, simple explanation on how to do this in the future or a link to an article that explains it well, that would be great.
You can get resources using a relative path or an absolute path. Relative paths start from the "working directory", which is the directory your application runs from. An absolute path is unambiguous. The working directory is checked before the classpath. This is what is used in places like
new File(filepath).
When you run Java, there is also the classpath to consider. Another way some people look for resources is
ClassLoader.getResource(String)
and
ClassLoader.getResourceAsStream(String)
The ClassLoader can accept the String as a relative path and will check each location along the classpath.
https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResourceAsStream(java.lang.String)
People get results by putting their files within the src folder because that usually gets copied over to the place where the class files are generated, which is included on the classpath.
The "top level" that you speak of is the working directory. Eclipse sets the working directory to the project root by default.
The relevant wikipedia page covers the file: scheme nicely.
But we live in a messy world, and various pieces of software may conform to older standards, or not conform completely with any standards, or may include support for alternate syntaxes. Understanding the correct syntax to use with a particular software system is unfortunately not always straightforward.

Relative path vs absolute paths

I have a java web application that reads files from the system, these files can be anywhere on the system.
I know if the file is in the webapp itself its always better to use relative path, but for files outside is it better to use absolute or relative? I just think using relative is a bit pointless, but many senior developers have suggested i use relative.
Would be interested in hearing thoughts, and what the practice is?
Normally, you should always use relative paths where possible. This is the best practice.
But if you can be absolutely (get it?) sure that file will stay there and is outside your actual application, you can refer it with an absolute path and it should be fine.
There are no real rules for when to use which... Id use it just for external stuff like this
The advantage you get with relative paths, obviously, is that its a lot more dynamic then using absolute paths.
It just depends on what you know. You have a webapp - that means that it's deployed on a server (like glassfish).
Up to the level of your servers folder it will be better to use relative paths - because you know the file structure up to that point and can localise everything without extra knowledge about the rest of the filesystem.
For files outside that you can't guarantee anything (it's perfectly legal to put and move server installation absolutely anywhere on the system) so absolute paths will be a more flexible choice.

Android: load java.io.file from resource file

I would like to use a Java library in my Android application. The class constructors and methods of this library often take paths to files (configuration file, dictionary, etc.) and then build java.io.file instances based on the given paths.
In my android application, I would like to store these file in the 'res' folder (possibly in res/raw). The problem is that I have to give a path to these files to the methods of the library.
I could easily get an InputStream using getResources(), but this would not be directly usable by my library. I would have to go through all the methods taking a path as an argument, replace it by an InputStream and modify the content to deal with InputStreams instead of Files. This represent quite a lot of work and I would much prefer to use the library without modification and keep it easily upgradable.
Even though using java.io.file based on resource file would not be a good practice, is it something possible? It would definitely help if you could indicate a way to do this.
Thank you.
If the library uses java.io.File then I don't think there is a way to do this in Java (let alone the Android subset of Java). It might be possible to solve the problem with a loopback filesystem, but this depends on your Android device's kernel, etc.
See:
https://android.stackexchange.com/questions/25396/how-to-find-out-if-my-devices-kernel-has-loop-device-support
If the library uses java.nio.file.Path, then it may be possible to implement a custom FileSystemProvider that maps the resources into the default file system namespace.
Note this is for regular Java 7. It would require a back-port of the relevant NIO libraries to get this to work on Android. I had another look for a viable backport, and couldn't find one.
See:
Tweaking the behavior of the default file system in Java 7
How to use java.nio.file package in android?
There is another "clunky" way to do this. Get your application to copy the relevant resources to files that can be accessed via a File.

Why operations over Path realized in form of static methods?

IMHO, path.delete() looks a little better than Files.delete(path). But developers of java.nio.file package preferred to realize operations over Path in form of Paths's static methods. Why?
It are utilitiy implementations, a design pattern as in Collection/Collections, File/Files, Path/Paths. Paths can handle different (virtual) "file" systems, like a zip file system. Hence a Path is associated with a file system, and a delete would delegate nevertheless to the file system delete. For instance:
For a zip file system view can have File path c:\data\x\y zip path relative x/y. You can move/rename/copy between paths. Having file operations reside in Path would be pure delegating calls.
They chose to let Path be a pure data structure even more than File, a bit like URL.
So there is some code design justification. But agreed, having several ~s classes, maybe used intermixed (Path+File+Paths+Files), does not make for a clean API style design.
Because, as the Javadoc states, a Path is
An object that may be used to locate a file in a file system. It will
typically represent a system dependent file path.
It's not actually a file, it just describes the path to the file. So there's nothing to delete or rather deleting doesn't make sense on a path. It only makes sense on a file.

Categories