Skip to content

Archive

Category: Java

A short post but I figured I would throw it up here before I lose my code. There are a couple of different ways that you can load jar’d code at runtime but here is a simple solution that I found to work very easily.

       File myJar = new File("myJar.jar");
       URL url = myJar.toURI().toURL();

       Class[] parameters = new Class[]{URL.class};

        URLClassLoader sysLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
        Class sysClass = URLClassLoader.class;
        try
        {
            Method method = sysClass.getDeclaredMethod("addURL", parameters);
            method.setAccessible(true);
            method.invoke(sysLoader,new Object[]{ url });

            Constructor cs = ClassLoader.getSystemClassLoader().loadClass("com.example.MyClass").getConstructor();
            MyInterface instance = (MyInterface)cs.newInstance();
            instance.someFunction();
        }
        catch(Exception ex)
        {
            System.err.println(ex.getMessage());
        }

In the code example above the jar at the location pointed to by the url object is dynamically loaded and an instance of the class com.example.MyClass is created that conforms to a known interface MyInterface. This could be used in a situation where you are loading plugins that use a common interface example.

For something to do I decided to see if I could create a very simple Java media player. After doing some research, and finding out that the Java Media Framework was no longer in development, I decided to settle on GStreamer to power my media player.

GStreamer for the uninitiated is a very powerful multimedia framework that offers both low-level pipeline building as well as high-level playback abstraction. What’s nice about GStreamer, besides being completely open source, is that it presents a unified API no matter what type of file it is playing. For instance if the user only has the free, high quality GStreamer codecs installed, referred to as the good plugins, then the API will only play those files. If however the user installs the other plugins as well, be it the bad or ugly sets, the API remains the same and thus you don’t need to update your code. Unfortunately being a C library this approach does have some drawbacks, notably the need to include the JNA jar as well as the system specific libraries. This approach can be considered similar to how SWT works.

Setup

Assuming that you already have a Java development environment, the first thing you’ll need is to install GStreamer. On Linux odds are you already have it, unless you are running a rather stripped down distro or don’t have many media players installed (both Rhythmbox and Banshee use GStreamer). If you don’t it should be pretty straight forward to install along with your choice of plugins. On Windows you’ll need to head over to ossbuild where they have downloadable installers.

The second thing you’ll need is gstreamer-java which you can grab over at their website here. You’ll need to download both gstreamer-java-1.4.jar and jna-3.2.4.jar. Both might contain some extra files that you probably don’t need and can prune out later if you’d like. Setup your development environment so that both of these jar files are in your build path.

Simple playback

GStreamer offers highly abstracted playback engines called PlayBins. This is what we will use to actually play our files. Here is a very simple code example that demonstrates how to actually make use of a PlayBin:

public static void main(String[] args) {
     args = Gst.init("MyMediaPlayer", args);

     Playbin playbin = new PlayBin("AudioPlayer");
     playbin.setVideoSink(ElementFactory.make("fakesink", "videosink"));
     playbin.setInputFile("song.mp3");

     playbin.setState(State.PLAYING);
     Gst.main();
     playbin.setState(State.NULL);
}

So what does it all mean?

public static void main(String[] args) {
     args = Gst.init("MyMediaPlayer", args);

The above line takes the incoming command line arguments and passes them to the Gst.init function and returns a new set of arguments. If you have ever done any GTK+ programming before this should be instantly recognizable to you. Essentially what GStreamer is doing is grabbing, and removing, any GStreamer specific arguments before your program will actually process them.

     Playbin playbin = new PlayBin("AudioPlayer");
     playbin.setVideoSink(ElementFactory.make("fakesink", "videosink"));
     playbin.setInputFile("song.mp3");

The first line of code requests a standard “AudioPlayer” PlayBin. This PlayBin is built right into GStreamer and automatically sets up a default pipeline for you. Essentially this lets us avoid all of the low-level craziness that we would have to normally deal with if we were starting from scratch.

The next line sets the PlayBin’s VideoSink, think of sinks as output locations, to a “fakesink” or null sink. The reason we do this is because PlayBin’s can play both audio and video. For the purposes of this player we only want audio playback so we automatically redirect all video output to the “fakesink”.

The last line is pretty straight forward and just tells GStreamer what file to play.

     playbin.setState(State.PLAYING);
     Gst.main();
     playbin.setState(State.NULL);

Finally with the above lines of code we tell the PlayBin to actually start playing and then enter the GStreamer main loop. This loop continues for the duration. The last line is used to reset the PlayBin state and do some cleanup.

Bundle it with a quick GUI

To make it a little more friendly I wrote a very quick GUI to wrap all of the functionality with. The download links for that (binary only package), as well as the source (all package) is below. And there you have it: a very simple cross-platform media player that will playback pretty much anything you throw at it.

Binary Only Package All Package
File name: my_media_player_binary.zip my_media_player_all.zip
File hashes: Download Here
GPG signature: Download Here Download Here
Screenshots:
Version: March 13, 2011
File size: 1.5MB 1.51MB
File download: Download Here Download Here

Java Web Start is a technology that allows easy deployment of Java based software through a web browser. The advantages of this framework are numerous but one nice thing is that it allows you far more freedom then the completely sandboxed Java applet. In this post I will detail how I converted my Hash Verifier application to run right from the browser.

Java Network Launching Protocol (JNLP)

The javax.jnlp libraries provide the functionality needed to launch the application from within a web browser. This is done through the use of a specially crafted XML file called a jnlp file. This file specifies the application information including the location of the executable jar and any class libraries associated with it. The nice thing about this is that it allows you to specify different class files spending on the platform it is being run on. This is exactly what I needed in order to get the correct SWT libraries loaded on the target platform.

As an example of what a jnlp file looks like here is the file I created for my Hash Verifier application:

<?xml version=”1.0″ encoding=”utf-8″?>
<jnlp spec=”1.0+” codebase=”http://www.tylerburton.ca/webstart” href=”hv.jnlp”>
<information>
<title>Hash Verifier</title>
<vendor>tylerburton.ca</vendor>
<homepage href=”http://tylerburton.ca” />
<description>A graphical file digest generator</description>
<description>Hash Verifier</description>
</information>

<security>
<all-permissions />
</security>

<resources>
<j2se version=”1.5+” />
<jar href=”HashVerifier.jar” />
</resources>

<resources os=”Windows” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-win32-windows-x86.jar” />
</resources>

<resources os=”Windows” arch=”x86_64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-win32-windows-x86_64.jar” />
</resources>

<resources os=”Windows” arch=”amd64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-win32-windows-x86_64.jar” />
</resources>

<resources os=”Linux” arch=”ppc”>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-ppc.jar” />
</resources>

<resources os=”Linux” arch=”ppc64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-ppc64.jar” />
</resources>

<resources os=”Linux” arch=”x86_64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86_64.jar” />
</resources>

<resources os=”Linux” arch=”amd64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86_64.jar” />
</resources>

<resources os=”Linux” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86.jar” />
</resources>

<resources os=”Linux” arch=”i386″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86.jar” />
</resources>

<resources os=”Linux” arch=”i686″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86.jar” />
</resources>

<resources os=”Mac” arch=”x86_64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86_64.jar” />
</resources>

<resources os=”Mac” arch=”amd64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86_64.jar” />
</resources>

<resources os=”Mac” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86.jar” />
</resources>

<resources os=”Mac” arch=”i386″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86.jar” />
</resources>

<resources os=”Mac” arch=”i686″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86.jar” />
</resources>

<resources os=”Mac”>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-carbon-mac.jar” />
</resources>

<resources os=”SunOS” arch=”sparc”>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-solaris-sparc.jar” />
</resources>

<resources os=”SunOS” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-solaris-x86.jar” />
</resources>

<application-desc main-class=”ca.tylerburton.hashverifier.HashVerifierMain” />

</jnlp>

As you can see I have outlined all of the platform configurations that I am going to be compatible with. Java Web Start takes care of the rest for me automatically.

Digital signatures

The final step is to digitally sign the executable jar. This is required because when deploying an application that is not sandboxed, or one that requires access to low-level functions and libraries (as is the case in SWT), the end user needs to know that the code they are receiving came directly from the source. The easiest way to do this is to follow the instructions here. Unfortunately unless you are willing to pay to have your certificate signed by a trusted certificate authority the end user will need to click OK through a big security warning before they can use your program. It’s a small issue to overcome but if Minecraft can do it without too much of a headache I’m sure you can too.

Easy deployment

It’s as simple as that. I didn’t have to re-write my code, heck I didn’t even have to adjust a single line and it all just works. To see the result on your platform click here.

Note: unfortunately there is an issue with the Mac version of Java Web Start & SWT that prevents it from working correctly. Until Apple fixes this, or OpenJDK takes over and does it, SWT applications cannot be started correctly on that platform through Web Start.

Both Java and Mono (the open source implementation of C# and .NET) will be receiving pretty big updates this year. These represent two very popular virtual machine based coding platforms that offer portability and a slew of helpful standard libraries. Here are just a handful of the improvements each will see in the coming release.

Java SE 7.0

While no tentative release date has been scheduled for Java 7 yet, the team has recently completed milestone 10 of 10. Sacrificing some features (which will be delayed until Java 8.0) Java 7 still has quite a few intriguing new additions.

  1. G1 (new garbage 1st garbage collector)

    This new garbage collector improves upon the original generational one by introducing the concept of regions. You can think of regions has smart versions of the generational lists that should allow the collector to clean up large chunks of garbage with increased efficiency.

  2. Dynamic language support

    The JVM will now support some internal changes which will allow dynamic languages (like Perl and Ruby) to leverage the speed and widespread nature of JVM for languages that aren’t strongly typed like Java. This in turn will will let dynamic languages have hooks into the standard Java libraries as well.

  3. NIO (New I/O)

    A new set of libraries for dealing with I/O. This will let Java do some interesting things like create symbolic links as well as giving general I/O operations a big performance boost.

  4. Native Java video libraries

    New standard video libraries will let the JVM playback and record video sources on any platform. No more relying on external libraries to do the job.

  5. Strings in switch statements

    I for one never really understood why you weren’t allowed to do this before. Obviously switch statements are highly optimized to act on numeric values but would it really be that hard for the compiler to change the string switch statement into an if statement for me? Now I don’t have to even think about it anymore.

  6. Automatic resource management

    Rather than having to worry about closing that I/O stream, Java will now take care of it for you. The new syntax is:do(BufferedInputStream bis = …) { //do some work} //it will automatically be closed here

  7. Others

    Other improvements include compressed 64-bit pointers to save memory, new parallel processing libraries to leverage multi-core CPUs and graphics acceleration improvements.

Mono 2.28

The folks over at the Mono team just finished up a new release that contains quite a few interesting additions as well.

  1. Full C#/ASP.NET 4.0 support

    This is nice to see because it means at the very least Mono and .NET are on equal footing when it comes to language syntax.

  2. New generational garbage collector

    Moving away from the older Boehm-Demers-Weiser garbage collector to a new generation garbage collector (a la Java) should mean improved performance at the temporary expense of extra memory usage. This should let the runtime decide the best time to schedule a garbage collection action and only focus on the objects most likely to need collection.

  3. Dynamic language support

    Similar to Java, this version of Mono now also supports the System.Dynamic libraries. Again this will allow dynamic languages to leverage the portable nature of Mono as well as hooking into the various Mono runtime libraries.

  4. New parallel libraries and frameworks

    These new libraries should make it even easier to create applications that make use of parallel processing. Among the libraries is PLINQ, an optimized version of LINQ for multi-core systems.

  5. Overall performance improvements

    Mono now targets LLVM which should make it better as a server platform. In addition there have been a lot of code fixes and performance improvements throughout the project. Finally this version of Mono has also removed Glib as a dependency which should make it lighter and more portable.

Back in this previous post I mentioned the possibility of putting up a sort of how-to guide on SWT programming. Well I’ve finally found some time to do so. I will try to make this as step-by-step as possible so that anyone reading this will completely understand what I’m doing.

What you’ll need

I’m making the following assumptions before starting:

  1. That you’ve already installed the Java Development Kit (not just the Java Runtime)
  2. That you’ve installed Eclipse. You can use an alternative but all of my examples will be based on Eclipse. I’m also going to assume that you are at least familiar enough with Eclipse to compile a Java program.
  3. That you have some understanding of Java or at least some programming experience.
  4. That you have the SWT library for your platform downloaded. You can find this on the download page here.
  5. That you’ve created a project in Eclipse (or your IDE) for this walk through.

Import SWT

The first thing you want to do is import the SWT libraries that you have downloaded as an Eclipse project. Start by creating a new project specifically for SWT. For instance I named mine org.eclipse.swt (following the Java standard namespace naming conventions). Next import the SWT files into that project. To do this simply click File > Import and then choose Archive File under the General folder.

Then browse to the zip file you downloaded and choose the project to import this to (again in my example this project is org.eclipse.swt). When all is said and done you should have a project in your workspace for SWT similar to the one I’ve got here:

SWTify your project

To finish adding the SWT libraries into your project we need to add them to your project’s class path. Right-click on your project and click properties. On the left hand side of the window you will see an item called Java Build Path. On that page there will be a number of tabs: Source, Projects, Libraries, etc. Click Projects and then click the Add button. Select the org.eclipse.swt project and click OK. You should see something like this indicating that the SWT libraries will be included in your project’s build path.

We are now ready to begin programming!

The default SWT program

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class MySWTProject {

     public static void main(String[] args) {

          Display display = new Display();
          Shell shell = new Shell(display);

          shell.open();

          while(!shell.isDisposed()) {
               if(!display.readAndDispatch()) {
                    display.sleep();
               }
          }

          display.dispose();
     }
}

OK so what does it mean. In SWT all of the graphical things that you can do are tied to a Display object. A Display is essentially a link to the OS’ underlying graphics output. What we are talking about is not a monitor – in fact a Display can contain multiple monitors – but rather a more abstracted concept of graphics. If this sounds confusing don’t worry, for the most part that’s all you’ll really need to know about the Display object.

A Shell should be a little easier to understand. It represents a window, the base application container. In fact if you run the above program you should see something like this:

A Shell can be manipulated in all of the ways that you think it would be. For instance you can give it a title by using the setText() method.

shell.setText(“Here is my window title”);

The open() method tells the Shell to start displaying itself. You can also do some interesting things like using the pack() method to size the Shell in order to make it just large enough to hold whatever you put into it.

The little while loop part first checks to make sure that our shell still exists and then executes any input that we may want our application to respond to (via the readAndDispatch() method). Finally we dispose of all resources we have requested from the OS by calling dispose() on the Display object. This is important because unlike regular Java programming we do not get automatic garbage collection in SWT. There is a silver lining however – calling dispose() on an object like Display will automatically call dispose() on any children that are registered with it. That is why we didn’t need to call dispose() on our Shell.

OK I get it, now show me a button

Interaction is very easy to add. For instance we can add a button to our Shell above by simply adding the following code after the line where we create our Shell.

     Button button = new Button(shell, SWT.PUSH);
     button.setText("Push Me");
     button.pack();

Of course you will also need to import the Button library for this to work. In the constructor we pass in the shell (where we want to attach this button, similar to how we attached our shell to the Display object) and a flag called SWT.PUSH. SWT.PUSH tells the button to act as a push button. Next using setText() again we set the button label. Finally using the pack() method, as described above, we can resize the button to be just large enough. If you re-run the program now you will should see something like the following:

Pretty simple stuff. We can even add an action listener that will respond when the button is pressed by using code like this:

button.addSelectionListener(new SelectionListener() {
    public void widgetDefaultSelected(SelectionEvent e) {
          widgetSelected(e);
     }

     public void widgetSelected(SelectionEvent e) {
          System.out.println("The button was pressed!");
     }
});

Again very simple. I hope that this very brief introduction will help people realize that SWT programming is very similar to regular AWT/Swing GUI creation (although each has their own unique weirdness). If you would like to download the sample code file that I used to create this you can do so here. Please let me know if you have any questions about what I have said above, I’d be happy to help. On the other hand if you want a more in-depth look feel, free to hop over to my Hash Verifier post and grab a copy of the source there. The Eclipse Foundation also has an excellent code snippet section here that will show you how to use each GUI widget.

Happy programming.