java.lang.UnsatisfiedLinkError even on setting -Djava.library.path - java

I am loading a library into my java code.
I have put the library in the sytem 32 folder and I have also set the -Djava.library.path.
Earlier this code was running
try{
System.loadLibrary("resources/TecJNI");
System.out.println("JNI library loaded \n");
}
catch(UnsatisfiedLinkError e){
System.out.println("Did not load library");
e.printStackTrace();
}
but since last week it is showing
java.lang.UnsatisfiedLinkError: no resources/TecJNI in java.library.path.
Is this some file permission issue for the dll that I am loading in the java code OR dll are using by some other application.
Also all other my running applications that were using & loading the same dll in different workspace are not running now.
Could anyone suggest me?
EDIT: I am using -
Djava.library.path="${workspace_loc}/org.syntec.ivb.application/resources;${env_var:PATH}"
in my eclipse vm arguments. I think it is using this.

when comes to load libs in jvm, I like to copy the libs to a temp directory, then load them from the temp directory. here is the code:
private synchronized static void loadLib(String dllPath,String libName) throws IOException {
String osArch = System.getProperty("os.arch").contains("64")?"_X64":"_X86";
String systemType = System.getProperty("os.name");
String libExtension = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll"
: ".so";
String libFullName = libName+osArch+ libExtension;
String nativeTempDir = System.getProperty("java.io.tmpdir");
InputStream in = null;
BufferedInputStream reader = null;
FileOutputStream writer = null;
File extractedLibFile = new File(nativeTempDir + File.separator
+ libFullName);
if (!extractedLibFile.exists()) {
try {
in = new FileInputStream(dllPath+ File.separator+
libFullName);
reader = new BufferedInputStream(in);
writer = new FileOutputStream(extractedLibFile);
byte[] buffer = new byte[1024];
while (reader.read(buffer) > 0) {
writer.write(buffer);
buffer = new byte[1024];
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null)
in.close();
if (writer != null)
writer.close();
}
}
System.load(extractedLibFile.toString());
}

System.loadLibrary expects library name, not a path. The path to the directory containg the library should be set in PATH (Windows) env variable or in -Djava.library.path

Why do you need the additional "resources"?
When using System.loadLibrary("resources/TecJNI"); you are looking for TecJNI.dll in a subfolder "resources" of the java.library.path. So if you put C:\windows\system32 on the library-path (which you wouldn't need since it's on the search-path by default) your library should be C:\windows\system32\resources\TecJNI.dll

Related

Java nio move folder with content throws exception [duplicate]

How do you move a file from one location to another? When I run my program any file created in that location automatically moves to the specified location. How do I know which file is moved?
myFile.renameTo(new File("/the/new/place/newName.file"));
File#renameTo does that (it can not only rename, but also move between directories, at least on the same file system).
Renames the file denoted by this abstract pathname.
Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful.
If you need a more comprehensive solution (such as wanting to move the file between disks), look at Apache Commons FileUtils#moveFile
With Java 7 or newer you can use Files.move(from, to, CopyOption... options).
E.g.
Files.move(Paths.get("/foo.txt"), Paths.get("bar.txt"), StandardCopyOption.REPLACE_EXISTING);
See the Files documentation for more details
Java 6
public boolean moveFile(String sourcePath, String targetPath) {
File fileToMove = new File(sourcePath);
return fileToMove.renameTo(new File(targetPath));
}
Java 7 (Using NIO)
public boolean moveFile(String sourcePath, String targetPath) {
boolean fileMoved = true;
try {
Files.move(Paths.get(sourcePath), Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
fileMoved = false;
e.printStackTrace();
}
return fileMoved;
}
File.renameTo from Java IO can be used to move a file in Java. Also see this SO question.
To move a file you could also use Jakarta Commons IOs FileUtils.moveFile
On error it throws an IOException, so when no exception is thrown you know that that the file was moved.
Just add the source and destination folder paths.
It will move all the files and folder from source folder to
destination folder.
File destinationFolder = new File("");
File sourceFolder = new File("");
if (!destinationFolder.exists())
{
destinationFolder.mkdirs();
}
// Check weather source exists and it is folder.
if (sourceFolder.exists() && sourceFolder.isDirectory())
{
// Get list of the files and iterate over them
File[] listOfFiles = sourceFolder.listFiles();
if (listOfFiles != null)
{
for (File child : listOfFiles )
{
// Move files to destination folder
child.renameTo(new File(destinationFolder + "\\" + child.getName()));
}
// Add if you want to delete the source folder
sourceFolder.delete();
}
}
else
{
System.out.println(sourceFolder + " Folder does not exists");
}
Files.move(source, target, REPLACE_EXISTING);
You can use the Files object
Read more about Files
You could execute an external tool for that task (like copy in windows environments) but, to keep the code portable, the general approach is to:
read the source file into memory
write the content to a file at the new location
delete the source file
File#renameTo will work as long as source and target location are on the same volume. Personally I'd avoid using it to move files to different folders.
Try this :-
boolean success = file.renameTo(new File(Destdir, file.getName()));
Wrote this method to do this very thing on my own project only with the replace file if existing logic in it.
// we use the older file i/o operations for this rather than the newer jdk7+ Files.move() operation
private boolean moveFileToDirectory(File sourceFile, String targetPath) {
File tDir = new File(targetPath);
if (tDir.exists()) {
String newFilePath = targetPath+File.separator+sourceFile.getName();
File movedFile = new File(newFilePath);
if (movedFile.exists())
movedFile.delete();
return sourceFile.renameTo(new File(newFilePath));
} else {
LOG.warn("unable to move file "+sourceFile.getName()+" to directory "+targetPath+" -> target directory does not exist");
return false;
}
}
Please try this.
private boolean filemovetoanotherfolder(String sourcefolder, String destinationfolder, String filename) {
boolean ismove = false;
InputStream inStream = null;
OutputStream outStream = null;
try {
File afile = new File(sourcefolder + filename);
File bfile = new File(destinationfolder + filename);
inStream = new FileInputStream(afile);
outStream = new FileOutputStream(bfile);
byte[] buffer = new byte[1024 * 4];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
// delete the original file
afile.delete();
ismove = true;
System.out.println("File is copied successful!");
} catch (IOException e) {
e.printStackTrace();
}finally{
inStream.close();
outStream.close();
}
return ismove;
}

Moving file from one directory to another and delete from source directory using java

I am trying to move files from one directory to another delete that file from source directory after moving.
for (File file : files) {
if (file != null) {
boolean status = moveFile(file, filePath, name, docGroupId);
if (status) {
//some operations....
}
}
}
public static boolean moveFile(final File file, final String filePath, final String groupName, Integer docGroupId) {
// TODO Auto-generated method stub
String selectedDirectory = filePath + File.separator + groupName;
InputStream in = null;
OutputStream out = null;
try {
if (!file.isDirectory()) {
File dir = new File(selectedDirectory);
if (!dir.exists()) {
dir.mkdirs();
}
String newFilString = dir.getAbsolutePath() +
File.separator + file.getName();
File newFile = new File(newFilString);
in = new FileInputStream(file);
out = new FileOutputStream(newFile);
byte[] moveBuff = new byte[1024];
int butesRead;
while ((butesRead = in.read(moveBuff)) > 0) {
out.write(moveBuff, 0, butesRead);
}
}
in.close();
out.close();
if(file.delete())
return true;
} catch (Exception e) {
return false;
}
}
The program works on Linux-Ubuntu and all files are moved to another directory and deleted from source directory, but in Windows system all files are moved but failed to delete one or two files from source directory. Please note that while debugging the program is working fine.
Consider using Files.delete instead of File.delete. The javadoc says:
Note that the Files class defines the delete method to throw an IOException when a file cannot be deleted. This is useful for error reporting and to diagnose why a file cannot be deleted.
This should provide the information necessary to diagnose the problem.
So, if problem comes with delete, possible explanations:
you do file.delete() on every files and directories. How do you know the directory is empty ? If not, it will fail, then what happen to next instructions ?
file deletion is OS-dependant. On Windows, you can have many security issues, depending on which user, which rights, which location. You should check with a file-delete-alone program;
last: files can be locked by other programs (even explorer), it is also OS-dependant.
You don't need any of this if the source and target are in the same file system. Just use File.renameTo().

Java - Running JAR refuses to load file in the same directory

Quick one. I'm trying to deploy a program, which borks at the following code. I want to read a properties file named, adequately, properties.
Properties props = new Properties();
InputStream is;
// First try - loading from the current directory
try {
File f = new File("properties");
is = new FileInputStream(f);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace(System.err);
is = null;
}
try {
if (is == null) {
// Try loading from classpath
is = getClass().getResourceAsStream("properties");
}
//Load properties from the file (if found), else crash and burn.
props.load(is);
} catch (IOException e) {
e.printStackTrace(System.err);
}
Everything goes well when I run the program through Netbeans.
When I run the JAR by itself, though, I get two exceptions.
java.io.FileNotFoundException: properties (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
.
.
.
Exception in Application start method
Exception in Application stop method
java.lang.reflect.InvocationTargetException
.
.
.
(exception during props.load(is) because is == null)
I'm running the file from the "dist" folder. I've tried placing the properties file inside the folder with the jar, without result. Normally, the properties file is located in the root project folder.
Any ideas?
You read your file as a resource (getResourceAsStream("properties");). So it must be in the classpath. Perhaps in the jar directly or in a directory which you add to the classpath.
A jar is a zip file so you can open it with 7zip for example add your properties file to the jars root level and try it again.
Thanks to the comments, I built an absolute path generator based on the current run directory of the jar. Props to you, guys.
private String relativizer(String file) {
URL url = RobotikosAnomologitos.class.getProtectionDomain().getCodeSource().getLocation();
String urlString = url.toString();
int firstSlash = urlString.indexOf("/");
int targetSlash = urlString.lastIndexOf("/", urlString.length() - 2) + 1;
return urlString.substring(firstSlash, targetSlash) + file;
}
So my new file-reading structure is:
Properties props = new Properties();
InputStream is;
// First try - loading from the current directory
try {
File f = new File("properties");
is = new FileInputStream(f);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace(System.err);
is = null;
}
try {
if (is == null) {
// Try loading from classpath
String pathToProps = relativizer("properties");
is = new FileInputStream(new File(pathToProps));
//is = getClass().getResourceAsStream(pathToProps);
}
//Load properties from the file (if found), else crash and burn.
props.load(is);
} catch (IOException e) {
e.printStackTrace(System.err);
}
// Finally parse the properties.
//code here, bla bla

How to copy files out of the currently running jar

I have a .jar that has two .dll files that it is dependent on. I would like to know if there is any way for me to copy these files from within the .jar to a users temp folder at runtime. here is the current code that I have (edited to just one .dll load to reduce question size):
public String tempDir = System.getProperty("java.io.tmpdir");
public String workingDir = dllInstall.class.getProtectionDomain().getCodeSource().getLocation().getPath();
public boolean installDLL() throws UnsupportedEncodingException {
try {
String decodedPath = URLDecoder.decode(workingDir, "UTF-8");
InputStream fileInStream = null;
OutputStream fileOutStream = null;
File fileIn = new File(decodedPath + "\\loadAtRuntime.dll");
File fileOut = new File(tempDir + "loadAtRuntime.dll");
fileInStream = new FileInputStream(fileIn);
fileOutStream = new FileOutputStream(fileOut);
byte[] bufferJNI = new byte[8192000013370000];
int lengthFileIn;
while ((lengthFileIn = fileInStream.read(bufferJNI)) > 0) {
fileOutStream.write(bufferJNI, 0, lengthFileIn);
}
//close all steams
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (UnsupportedEncodingException e) {
System.out.println(e);
return false;
}
My main problem is getting the .dll files out of the jar at runtime. Any way to retrieve the path from within the .jar would be helpful.
Thanks in advance.
Since your dlls are bundeled inside your jar file you could just try to acasses them as resources using ClassLoader#getResourceAsStream and write them as binary files any where you want on the hard drive.
Here is some sample code:
InputStream ddlStream = <SomeClassInsideTheSameJar>.class
.getClassLoader().getResourceAsStream("some/pack/age/somelib.dll");
try (FileOutputStream fos = new FileOutputStream("somelib.dll");){
byte[] buf = new byte[2048];
int r;
while(-1 != (r = ddlStream.read(buf))) {
fos.write(buf, 0, r);
}
}
The code above will extract the dll located in the package some.pack.age to the current working directory.
Use a class loader that is able to locate resources in this JAR file. Either you can use the class loader of a class as Peter Lawrey suggested, or you can also create a URLClassLoader with the URL to that JAR.
Once you have that class loader you can retrieve a byte input stream with ClassLoader.getResourceAsStream. On the other hand you just create a FileOutputStream for the file you want to create.
The last step then is to copy all bytes from the input stream to the output stream, as you already did in your code example.
Use myClass.getClassLoader().getResourceAsStream("loadAtRuntime.dll"); and you will be able to find and copy DLLs in the JAR. You should pick a class which will also be in the same JAR.

How to get a path to a resource in a Java JAR file

I am trying to get a path to a Resource but I have had no luck.
This works (both in IDE and with the JAR) but this way I can't get a path to a file, only the file contents:
ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));
If I do this:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());
The result is:
java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
Is there a way to get a path to a resource file?
This is deliberate. The contents of the "file" may not be available as a file. Remember you are dealing with classes and resources that may be part of a JAR file or other kind of resource. The classloader does not have to provide a file handle to the resource, for example the jar file may not have been expanded into individual files in the file system.
Anything you can do by getting a java.io.File could be done by copying the stream out into a temporary file and doing the same, if a java.io.File is absolutely necessary.
When loading a resource make sure you notice the difference between:
getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path
and
getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning
I guess, this confusion is causing most of problems when loading a resource.
Also, when you're loading an image it's easier to use getResourceAsStream():
BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));
When you really have to load a (non-image) file from a JAR archive, you might try this:
File file = null;
String resource = "/com/myorg/foo.xml";
URL res = getClass().getResource(resource);
if (res.getProtocol().equals("jar")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile("tempfile", ".tmp");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.close();
file.deleteOnExit();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
if (file != null && !file.exists()) {
throw new RuntimeException("Error: File " + file + " not found!");
}
The one line answer is -
String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()
Basically getResource method gives the URL. From this URL you can extract the path by calling toExternalForm().
I spent a while messing around with this problem, because no solution I found actually worked, strangely enough! The working directory is frequently not the directory of the JAR, especially if a JAR (or any program, for that matter) is run from the Start Menu under Windows. So here is what I did, and it works for .class files run from outside a JAR just as well as it works for a JAR. (I only tested it under Windows 7.)
try {
//Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
//Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
//Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.
//Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
try {
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
} catch (Exception e) { }
//Find the last / and cut it off at that location.
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
//If it starts with /, cut it off.
if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
//If it starts with file:/, cut that off, too.
if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
PROGRAM_DIRECTORY = ""; //Current working directory instead.
}
This is same code from user Tombart with stream flush and close to avoid incomplete temporary file content copy from jar resource and to have unique temp file names.
File file = null;
String resource = "/view/Trial_main.html" ;
URL res = getClass().getResource(resource);
if (res.toString().startsWith("jar:")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile(new Date().getTime()+"", ".html");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
input.close();
file.deleteOnExit();
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
if netclient.p is inside a JAR file, it won't have a path because that file is located inside other file. in that case, the best path you can have is really file:/path/to/jarfile/bot.jar!/config/netclient.p.
You need to understand the path within the jar file.
Simply refer to it relative. So if you have a file (myfile.txt), located in foo.jar under the \src\main\resources directory (maven style). You would refer to it like:
src/main/resources/myfile.txt
If you dump your jar using jar -tvf myjar.jar you will see the output and the relative path within the jar file, and use the FORWARD SLASHES.
In my case, I have used a URL object instead Path.
File
File file = new File("my_path");
URL url = file.toURI().toURL();
Resource in classpath using classloader
URL url = MyClass.class.getClassLoader().getResource("resource_name")
When I need to read the content, I can use the following code:
InputStream stream = url.openStream();
And you can access the content using an InputStream.
follow code!
/src/main/resources/file
streamToFile(getClass().getClassLoader().getResourceAsStream("file"))
public static File streamToFile(InputStream in) {
if (in == null) {
return null;
}
try {
File f = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
f.deleteOnExit();
FileOutputStream out = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
return f;
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
return null;
}
}
A File is an abstraction for a file in a filesystem, and the filesystems don't know anything about what are the contents of a JAR.
Try with an URI, I think there's a jar:// protocol that might be useful for your purpouses.
The following path worked for me: classpath:/path/to/resource/in/jar
private static final String FILE_LOCATION = "com/input/file/somefile.txt";
//Method Body
InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);
Getting this from getSystemResourceAsStream is the best option. By getting the inputstream rather than the file or the URL, works in a JAR file and as stand alone.
It may be a little late but you may use my library KResourceLoader to get a resource from your jar:
File resource = getResource("file.txt")
Inside your ressources folder (java/main/resources) of your jar add your file (we assume that you have added an xml file named imports.xml), after that you inject ResourceLoader if you use spring like bellow
#Autowired
private ResourceLoader resourceLoader;
inside tour function write the bellow code in order to load file:
Resource resource = resourceLoader.getResource("classpath:imports.xml");
try{
File file;
file = resource.getFile();//will load the file
...
}catch(IOException e){e.printStackTrace();}
Maybe this method can be used for quick solution.
public class TestUtility
{
public static File getInternalResource(String relativePath)
{
File resourceFile = null;
URL location = TestUtility.class.getProtectionDomain().getCodeSource().getLocation();
String codeLocation = location.toString();
try{
if (codeLocation.endsWith(".jar"){
//Call from jar
Path path = Paths.get(location.toURI()).resolve("../classes/" + relativePath).normalize();
resourceFile = path.toFile();
}else{
//Call from IDE
resourceFile = new File(TestUtility.class.getClassLoader().getResource(relativePath).getPath());
}
}catch(URISyntaxException ex){
ex.printStackTrace();
}
return resourceFile;
}
}
When in a jar file, the resource is located absolutely in the package hierarchy (not file system hierarchy). So if you have class com.example.Sweet loading a resource named ./default.conf then the resource's name is specified as /com/example/default.conf.
But if it's in a jar then it's not a File ...
This Class function can get absolute file path by relative file path in .jar file.
public class Utility {
public static void main(String[] args) throws Exception {
Utility utility = new Utility();
String absolutePath = utility.getAbsolutePath("./absolute/path/to/file");
}
public String getAbsolutePath(String relativeFilePath) throws IOException {
URL url = this.getClass().getResource(relativeFilePath);
return url.getPath();
}
}
If target file is same directory with Utility.java, your input will be ./file.txt.
When you input only / on getAbsolutePath(), it returns /Users/user/PROJECT_NAME/target/classes/. This means you can select the file like this /com/example/file.txt.

Categories

Resources