Lambdas and serialization

With the introduction of intersection cast in Java 8, it is now possible to write: Object o = (SomeType & SomeOtherType) otherObject;

One very interesting use case is Serialization as this allows us to automagically serialize a lambda effortlessly:

    File file = Files.createTempFile("lambda", "ser").toFile();
    try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(file))) {
        Runnable r = (Runnable & Serializable) () -> System.out.println("I can be serialized!");
        oo.writeObject(r);
    }

    try (ObjectInput oi = new ObjectInputStream(new FileInputStream(file))) {
        Runnable  r = (Runnable) oi.readObject();
        r.run();
    }
Tagged , , ,

Memory conscious toList collector with Java 8

The following code:

    List source = Arrays.asList(1, 2, 3, 4, 5);
    List result = new ArrayList<> (source.size());
    for (int i : source) result.add(2 * i);

can easily be transformed to use lambdas in Java 8, for example:

    List result = source.stream()
                                 .map(i -> 2 * i)
                                 .collect(toList());

There is however an important difference: in the first code, the result list has a capacity of 5, whereas in the second code it has a capacity of 10, hence using more memory*.

The Collectors utility class also offers a toCollection method which accepts a Supplier<Collection>. That method allows to use a properly sized collection, for example:

    Supplier s = () -> new ArrayList<>(source.size());
    List result = source.stream()
                                 .map(i -> 2 * i)
                                 .collect(toCollection(s));

The code is now equivalent to the original code without lambdas and the result list has an optimal capacity.


*The capacity of the backing array can easily be checked with:

    Field f = ArrayList.class.getDeclaredField("elementData");
    f.setAccessible(true);
    System.out.println(((Object[]) f.get(result)).length);


Tagged , , ,

Transparent background with JavaFX

Something that can be useful is to have a transparent background. For example if one wants to show several components as if they were free-floating windows while keeping them all within the same Stage.

It can be achieved by making each layer transparent (Stage, Scene, Nodes). Here is a simple example that shows how it can be done:

public class TransparentWindow extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        try {
            Label lbl = new Label("LABEL");
            VBox p = new VBox(lbl);

            //make the background of the label white and opaque
            lbl.setStyle("-fx-background-color: rgba(255, 255, 255, 1);");

            //add some borders to visualise the element' locations
            lbl.setBorder(new Border(new BorderStroke(Color.BLUE, BorderStrokeStyle.SOLID, null, null)));
            p.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, null, null)));

            Scene scene = new Scene(p);
            stage.setScene(scene);

            //this is where the transparency is achieved:
            //the three layers must be made transparent
            //(i)  make the VBox transparent (the 4th parameter is the alpha)
            p.setStyle("-fx-background-color: rgba(0, 0, 0, 0);");
            //(ii) set the scene fill to transparent
            scene.setFill(null);
            //(iii) set the stage background to transparent
            stage.initStyle(TRANSPARENT);

            stage.setWidth(200);
            stage.setHeight(100);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

And the result looks like this (with my IDE in the background):

Capture

The next step is to add some custom buttons to allow the user to close the window (if you run the example as is you will need to kill the application).

Tagged , , ,

Installing a web server for a Java Webstart Deployment

The goal is to install a HTTP server on a linux box (debian) and place the files from a Java project in there to allow a deployment via Java Webstart. This is a reminder for myself, nothing that can’t be found by googling a little.

Install a HTTP server

I used apache as a server (it just works, there might be better options):

apt-get update
apt-get install apache2 apache2-doc apache2-utils

Check that the procedure worked by trying to access the server at http://hostnameOrIp, which should show a default web page.

That default page is located in /var/www, so you can start placing files in there as you wish.

Optional: make the folder available to Windows computers on the network via Samba:

Add the following profile to /etc/samba/smb.conf

[www]
   comment = Web Server
   path = /var/www
   guest ok = yes
   browseable = yes
   writeable = yes
   create mask = 0777
   directory mask = 0777

Change the permissions:

sudo chmod 777 -R /var/www

And restart Samba:

/etc/init.d/samba restart

Prepare the Java project files

I assume that the project is packaged as a JAR file, with a certain number of dependencies, available as JAR files too.

You can then sign and deploy the files to the server, with the associated JNLP file.

Prepare the index.html

A very basic html page containing a "launch" button:

<html><body>
    <script src= "http://www.java.com/js/deployJava.js"></script>
    <script>
        // using JavaScript to get location of JNLP
        // file relative to HTML page
        var dir = location.href.substring(0, location.href.lastIndexOf('/')+1);
        var url = dir + "YourJnlp.jnlp";
        deployJava.createWebStartLaunchButton(url);
    </script>
</body></html>
Tagged , ,

JavaFX 2 & Maven

One of the annoying thing with JavaFX 2 is that it is co-bundled with the JDK since Java 7u7 but is not on the classpath by default.

One way, in Netbeans, is to create a Maven JavaFX project (although I have been somewhat unlucky with that approach).

There are various alternatives proposed on the web – one that worked for me consists in playing with the pom file to include JavaFX in the classpath with:

<dependency>
    <groupId>javafx</groupId>
    <artifactId>jfxrt</artifactId>
    <scope>system</scope>
    <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
    <version>2.2.4</version>
</dependency>

Although this might not be the best approach, it seems to work fine.

Tagged , ,

Java micro benchmark with jmh and Netbeans

Note that jmh has evolved significantly since I wrote this post and some of the information below might be obsolete.

jmh (Java Microbenchmark Harness) is an open source micro-benchmarking tool for java, part of the OpenJDK. I have been using it for a few weeks and found it easy to use and very useful. One advantage it has over Caliper is that it runs on Windows.

Installation

The installation process is fairly straight-forward using Maven. For example, with Netbeans, it can be done following those steps:

  • Download source (you need to have Mercurial installed):

  • Open, compile and install the library:

    • Netbeans then proposes to open the project: click Open Projects
    • Select the top project and click open
    • Right click on the project > Custom > Goals
    • In Goals, type: clean install -DskipTests=true

Create a Microbenchmark Project

  • Menu File > New Project
  • Select Maven / Java Application > Next
  • Let’s call it performance
  • Enter a GroupID (I use com.assylias for this example)
  • Click Finish

Let’s now configure the dependencies and allow the project to run jmh:

  • In the project’s Project Files, select and edit pom.xml
  • Use the following dependencies and build settings:

<dependencies>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <finalName>microbenchmarks</finalName>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>org.openjdk.jmh.Main</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Sample benchmark

Let’s try to benchmark something to see if it works. We could for example try to find the best method to copy an array. The four candidates we are going to test are:

  • Object[] newArray = originalArray.clone();
  • Object[] newArray = Arrays.copyOf(originalArray, originalArray.length);
  • System.arrayCopy(originalArray, 0, newArray, 0, originalArray.length);
  • and a plain old loop

In your project source package, right click and add a new class, let’s call it ArrayCopy, and copy the following code:

import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.BenchmarkType;
import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

/**
 *
 */
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class ArrayCopy {

    private int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    @GenerateMicroBenchmark(BenchmarkType.AverageTimePerOp)
    public int[] clone_() {
        int[] copy = array.clone();
        return copy;
    }

    @GenerateMicroBenchmark(BenchmarkType.AverageTimePerOp)
    public int[] arrayCopy() {
        int[] copy = new int[array.length];
        System.arraycopy(array, 0, copy, 0, array.length);
        return copy;
    }

    @GenerateMicroBenchmark(BenchmarkType.AverageTimePerOp)
    public int[] copyOf() {
        int[] copy = Arrays.copyOf(array, array.length);
        return copy;
    }

    @GenerateMicroBenchmark(BenchmarkType.AverageTimePerOp)
    public int[] loop() {
        int[] copy = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            copy[i] = array[i];
        }
        return copy;
    }    
}

Finally, let’s create the launcher that will run the micro-benchmark – I use this runner class (alternatively you can run it from the command line but I’m lazy and prefer running it from the IDE):

import java.io.IOException;
import org.openjdk.jmh.Main;

public class RunTest {
    private static final String TEST = ".*ArrayCopy.*"; //uses regexp

    public static void main(String[] args) throws IOException {
        Main.main(getArguments(TEST, 5, 5000, 1));
    }

    private static String[] getArguments(String className, int nRuns, int runForMilliseconds, int nThreads) {
        return new String[]{className,
            "-i", "" + nRuns,
            "-r", runForMilliseconds + "ms",
            "-t", "" + nThreads,
            "-w", "5000ms",
            "-wi", "3",
            "-v"
        };
    }
}

Clean and Build the project (CTRL+F11) and run it (SHIFT+F6 with the RunTest class selected).

You should get a detailed output of the performance of the various methods and a summary table that looks like this:

Benchmark                       Thr    Cnt  Sec         Mean   Mean error          Var    Units
c.a.p.g.a.ArrayCopy.arrayCopy     1     10    1       11.947        0.049        0.002  nsec/op
c.a.p.g.a.ArrayCopy.clone_        1     10    1       11.801        0.368        0.128  nsec/op
c.a.p.g.a.ArrayCopy.copyOf        1     10    1       11.783        0.115        0.013  nsec/op
c.a.p.g.a.ArrayCopy.loop          1     10    1       17.985        0.109        0.011  nsec/op

Next steps

The jmh project comes with a few samples which are very interesting and useful to read. It is also useful to check the usage, for example with the printUsage method in the example above (or by running it from the command line with no argument: java -jar microbenchmarks.jar).

Tagged , , , ,

Installing ubuntu/debian with PXE using a Windows machine

There is an official tutorial on Ubuntu’s website to install Ubuntu over the network via PXE, using a Windows machine as a DHCP/TFTP server.

I managed to make it work after a few hours of struggle because one crucial piece of information was unclear/missing. The same procedure is applicable for Debian.

You need to:

  • delete pxelinux.0 and pxelinux.cfg from the root of the created netboot/ folder
  • copy netboot/ubuntu-installer/amd64/pxelinux.0 to netboot/ (path will vary depending on what you are installing)
  • create a pxelinux.cfg folder in the netboot/ folder
  • copy the proper version of default to the netboot/pxelinux.cfg/ folder you just created (once again, the location will vary depending on what distribution you are installing)

I used the following options in tftp32:

  • Current directory: C:\tftp\netboot
  • Settings

    • GLOBAL: TFTP Server + DHCP Server
    • TFTP: Base Directory: C:\tftp\netboot | PXE Compatibility | Bind to this adress
    • DHCP: Pool starting address: beginning of an unused IP range | Size: 10 | Boot file: pxelinux.0 | WINS/DNS: DNS IP | Router: Router IP | Mask: network mask | Select 3 options: Ping, Bind, Persistent

And don’t forget to turn off other DHCP servers on your network!

Tagged , ,
Follow

Get every new post delivered to your Inbox.