Updated 11 March 2008

Introduction

JavaConnect is a Visualworks Smalltalk library that allows a seamless interaction between Smalltalk and Java. A Smalltalk application can access any Java object and send messages to it, just as if it were a Smalltalk object. Its implementation relies on a connection between the Smalltalk environment and a standard Java VM environment using Visualworks' DLLCC and Java's JNI. The Java application thus executes on a regular Java VM and the Smalltalk application executes on the regular Smalltalk VM.

JavaConnect was developed to enable SOUL to reason over Java programs without reimplementing many of the readily available Java libraries and utilities that exist for this purpose. In particular, we are using the Java libraries Soot and the Eclipse JDT to reason about Java programs from within Smalltalk. JavaConnect makes these Java utilities and libraries available as Smalltalk libraries, and thus makes them directly usable by tools implemented in Smalltalk. Cava is the SOUL extension containing a set of logic rules and all required functionality to use the abovementioned Java libraries. JavaConnect was inspired by the JNIPort for Dolphin and JavaInSt work. The JNIPort now also has a Visualworks version, but we also continue to maintain and develop JavaConnect. Please feel free to explore, test and use this work!

JavaConnect was used to demonstrate the advantages of computational reflection in dynamic programming languages. Check out the presentation that was used during the course on reflection in programming languages.

JavaConnect is released under the MIT Open Source License.

Download and Get Started!

JavaConnect is written for Visualworks Smalltalk, works with the latest Java versions and has been tested on Mac (PPC and Intel), Linux and Windows.

Basics

Java packages

JavaConnect maps Java packages onto Visualworks' namespaces beneath the JavaWorld root namespace. The java package java.lang.util, for example, is represented by the JavaWorld.java.lang.util namespace. For convenience, the java sub-namespace has been imported into the Smalltalk namespace, allowing to omit a reference via JavaWorld to refer to classes and sub-namespaces of the java namespace from any Smalltalk code.

In addition, the refactoring browser's package tab shows the java packages that are currently available on the classpath of the loaded and running Java VM. These Java packages are not to be confused with the Smalltalk packages and are therefore rooted in JavaWorld keyword instead of the Local Image keyword.

Java classes

Regular Java classes are represented using regular Smalltalk classes with the same name and are accessible via the namespace that represents their corresponding Java package. The Java Date class, for example, is accessible as JavaWorld.java.lang.util.Date . Member classes are also represented using regular Smalltalk classes but their name is prefixed with their parent class(es) name(s) and includes the separator '_' between all the names. The Iterator class, member class of the List class in the java.lang.util package, for example, is represented by the JavaWorld.java.lang.util.List_Iterator class in Smalltalk.

The refactoring browser displays the list of classes contained in a Java package in the class tab of the refactoring browser.

Java objects

Java objects can be created by invoking the constructors defined on the class via different variants of the new message. This is explained in the next section. The resulting Java objects can be manipulated like any Smalltalk object. Java objects are, of course, also obtained as return results from the invocation of Java methods. JavaConnect guarantees that identical Java objects are uniquely represented in the Smalltalk image. This means that object comparison of Java objects in Smalltalk works and that the same actual Java object (living in the Java VM) is consistently represented by a unique Java object in the Smalltalk image.

Java objects can be inspected using the regular Smalltalk inspectors.

Java methods

The public methods of a Java class are represented as regular Smalltalk methods, except for a pre-defined and automatic conversion from Java's method-name syntax onto Smalltalk's message syntax. This means that the Java methods are available as regular Smalltalk methods. Furthermore, similar to any Smalltalk class, the static methods of the Java class can only be invoked on the class itself, while the normal methods can only be invoked on instance objects of the class.

The method-name conversion scheme is as follows:

The refactoring browser displays all methods of a Java class in the 'native Java methods' protocol of the class. Instance methods and class (static) methods are displayed in their corresponding tab.

Java constructors

The public constructors of a Java class are mapped onto corresponding Smalltalk class methods. The name conversion scheme for constructors is identical to the one for methods, but the name of a constructor is always mapped onto 'new'. This means that zero-argument constructors are mapped onto the new class-method and multiple argument constructors are mapped onto keyworded messages of which the first keyword is prefixed with 'new'. For example, the Java constructor Date(int year, int month, int date) is represented as the Smalltalk class method with selector new_int:int:int: (implemented on the Date class).

The constructors of each Java class are displayed by the refactoring browser as class methods in the 'java native constructors' protocol.

Java fields

Public fields of a Java object are made available by automatically generated accessors and mutators. The accessor and mutator methods are prefixed with 'get_' and 'put_' respectively, following the name of the field. Static fields are accessible via class methods, while instance fields are accessible via instance methods.

Typing

Smalltalk programmers are only confronted with Java's static typing through the names of the messages that are sent to Java objects and classes. As we explained, these names are composed of the simple type names of each method parameter. From within Smalltalk, we are not concerned about the static return type of the method we invoke because JavaConnect always returns an object of the dynamic return type of the method. Of course, we must also ensure to pass the right argument objects to the methods, as the Java VM will throw a typing exception otherwise. But, this is no different from invoking a Smalltalk method. The current version of JavaConnect does not allow to pass Smalltalk objects to Java methods, but the upcoming version will allow to pass any kind of Smalltalk object to Java and even have Java invoke Smalltalk methods.

Conversion of Java values into Smalltalk values, and vice-versa.

As Java makes a difference between native and reference types, JavaConnect also differentiates between these two kinds of values.

All native values (int, float, double, char, ...) are automatically converted into their Smalltalk counterparts and vice-versa. You can thus pass any such Smalltalk value where a native Java value is expected and you will get a Smalltalk value back when a method returns a native type.

All reference values (i.e. class types), are represented in Smalltalk as instances of their corresponding classes. For example, a Java String object will thus not be converted automatically into a Smalltalk String object but will be represented as an instance of the JavaWorld.java.lang.String class.

In order to convert a Java String object into a corresponding Smalltalk String object, you can send the #asSmalltalkValue message to the Java String object. This pre-defined Smalltalk method on the Java String class will return a new Smalltalk String object with the same textual content as the Java String object. Inversely, it is possible to pass a Smalltalk String object where a Java String object is expected. This is because JavaConnect always tries to convert any Smalltalk object being passed to a Java method into a corresponding Java object. This is done by invoking the #asJavaValue message on the Smalltalk object, which should result in an appropriate Java object. JavaConnect includes a predefined implementation for Smalltalk values of String, Boolean, Integer, Character, Array, and many more. Just take a look at the implementors of #asJavaValue.

Developers can also implement custom #asSmalltalkValue and #asJavaValue methods on any Java or Smalltalk class using the prototyping mechanism, which is explained later on.

Interfaces?

JavaConnect does not care about Java interfaces. The only exception being for values of anonymous member classes, which are then represented in Smalltalk as objects of the static return type of the method through which they are obtained. As this static return type can be an interface type, an interface can appear as a Smalltalk class in the image.

Java Exceptions

Exceptions thrown by the Java methods are converted into Smalltalk exceptions containing an instance of JavaWorld.java.lang.Throwable. The mechanism is quite basic at this moment and is bound for improvement in the future.

Adding Smalltalk code and state to Java classes

JavaConnect features a mechanism of so-called 'prototypes' which allow to add Smalltalk methods to the represented Java classes in our image. This mechanism is bound to change, so we will include further information about it in the future. In the meantime, you can, for example, note the implementation of some Smalltalk methods defined on the common superclass of all Java classes (i.e. JavaObject) and in the JavaConnect package 'JavaConnect-JavaClassExtensions'.

Passing Smalltalk objects to Java methods

Will be possible in the upcoming version.

Java calls backs to Smalltalk

Will be possible in the upcoming version.

System.out and System.err

JavaConnect redirects the JVM's System.out and System.err printstreams so you can access them from Smalltalk.

Java VM configurations

When you start JavaConnect, the JVM is started with a set of options that correspond to the command-line options you can pass to the 'java' executable. The most important option of a configuration is the classpath parameter. It determines which Java classes you can load and use. A fresh download of JavaConnect contains some pretty useless configurations with empty classpaths. This means that only the standard Java classes are available. Fortunately, you can create your own configurations very easily.

The class JavaVMOptions has a class-side protocol called 'predefined configurations'. Each method in this protocol defines a configuration. You can add a configuration by defining a new method in this protocol. Upon execution, the method MUST return a JavaVMOptions instance that holds all desirable options for your configuration. Take a look at the existing methods how to name your configuration and how to add options to it. The most important option, the classpath, has a convenience method to set it using a string.

Applications that use JavaConnect provide more configuration examples. Check those out if you need more In the future, we also plan to implement a settings tool.

Screenshots (click to enlarge)

Browsing Java classes and their methods in the standard Smalltalk Refactoring Browser.

A preliminary version of the JavaConnect settings tab in the Visualworks settings. In the current version it allows to change the library locations but is still bound to change in the future.

JavaConnect loaded in the Visualworks Smalltalk environment !

Some Code Examples

Let's illustrate some usages of JavaConnect with some code examples.

       zipfile := JavaWorld.java.util.zip.ZipFile new_String:'foo.zip'.
       zipfile size inspect.
       entries := zipfile entries.
       [entries hasMoreElements] whileTrue:[Transcript show: entries nextElement]

Need to know more?

If you're interested to learn about the implementation, or if you want to make adaptations, or anything else: Please contact me

Here is a presentation explaining the basics of JavaConnect