Creating Symbolic Links with Java at Runtime

For the time being it seems that there is no other way than calling an external program for doing the job:

Process process = Runtime.getRuntime().exec( new String[] { "ln", "-s", oldName, newname } );
process.waitFor();
process.destroy();

The disadvantage of this method is the overhead for creating the new process. This can be a serious downgrade in performance if you have to execute this code frequently.

Here is an alternative solution that can vastly improve speed.

First you write a small program in C, say it symlinkcreator.c. This is the actual worker:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

int main()
{
char st[1024];
char oldpath[1024];
int count = 0;

while (fgets(st,sizeof(st),stdin) != NULL)
{
for (char *cp = st; *cp; cp++)
if (*cp == 'n' || *cp == 'r') *cp = '';

if (count++ % 2)
symlink(oldpath,st);
else
strcpy(oldpath,st);
}
}

You can compile the program by running this command:

# gcc symlinkcreator.c -o symlinkcreator -std=c99

This will give you the symlinkcreator executable file.

Then you going to need an elegant wrapper class that will call the C program:

import java.io.IOException;
import java.io.PrintWriter;

public class SymlinkCreator
{
private Process process;
private PrintWriter out;

public SymlinkCreator( String path ) throws IOException
{
process = Runtime.getRuntime().exec(path);
out = new PrintWriter(process.getOutputStream());
}

public void link( String oldpath, String newpath )
{
out.println(oldpath);
out.println(newpath);
out.flush();
}

public void terminate() throws InterruptedException
{
out.close();
process.waitFor();
process.destroy();
}
}

Have done these, you can then easily create symbolic links from you code, like this:

// You only need one single SymlinkCreator object (just a single unix process is created)
SymlinkCreator symlinkCreator = new SymlinkCreator("/path/to/symlinkcreator");
...
// Create as many symbolic links as you want using the same process
symlinkCreator.link(oldName,newName);
...
// Terminate the symbolic creator process and release resources when done.
symlinkCreator.terminate();

Downloads:
symlinkcreator.c

SymlinkCreator.java


Alternatively, you can use native methods to eliminate the hassle of inter-process communication between two separate processes.

First create a Symlink class that defines the signatures of the native mathod. This class will act as an interface to the actual C functions:

public class Symlink
{
public native static void create( String oldpath, String newpath );
}

Then you will need to generate a header file for this class using the javah utility:

# javah -classpath /path/to/your/classes Symlink

This will generate a header file that looks like this:

Symlink.h

#include <jni.h>
/* Header for class Symlink */

#ifndef _Included_Symlink
#define _Included_Symlink
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     Symlink
* Method:    create
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Symlink_create
(JNIEnv *, jclass, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif

Then you will have to write a small C file that will define the implemtation of the  function:

Symlink.c

#include <unistd.h>

#include <jni.h>

#include "Symlink.h"

JNIEXPORT void JNICALL Java_Symlink_create
(JNIEnv *env, jclass obj, jstring oldpath, jstring newpath)
{
const char *nativeOldpath = (*env)→GetStringUTFChars(env, oldpath, 0);
const char *nativeNewpath = (*env)→GetStringUTFChars(env, newpath, 0);

symlink(nativeOldpath,nativeNewpath);

(*env)→ReleaseStringUTFChars(env, oldpath, nativeOldpath);
(*env)→ReleaseStringUTFChars(env, newpath, nativeNewpath);
}

Then you have to compile the C file as a shared library:

# gcc -shared -o Symlink.so Symlink.c -I /path/to/jdk/include -I /path/to/jdk/include/linux

You will have to load this shared library at the runtime of your java program.

Finally you can write a small test program to see that everything works:

public class TestSymlink
{
public static void main( String[] args )
{
System.load("/path/to/Symlink.so");
Symlink.create("/home/giannis/test1", "/home/giannis/test2");
}
}

This entry was posted in Uncategorized. Bookmark the permalink.

2 Responses to Creating Symbolic Links with Java at Runtime

  1. Clarissa says:

    Just desire to say your article is as amazing. The clarity in your put up is simply spectacular and that i could think you are an expert on this subject.
    Fine together with your permission let me to grab your RSS feed
    to keep up to date with imminent post. Thank you a million and please continue the rewarding work.

Leave a Reply

Your email address will not be published. Required fields are marked *