This is the README file for the JavaScript LiveConnect Version 3 ("LC3") implementation.

Table of Contents

Introduction
New features
Compatibility
Limitations/Bugs/To-Do
Build conventions
Naming and coding conventions
The LiveConnect API
Sample LiveConnect shell interactions

Introduction

LiveConnect is a library that permits JavaScript and Java virtual machines to interoperate. Specifically, it enables JavaScript to access Java fields, invoke Java methods and enables Java to access JavaScript object properties and evaluate arbitrary JavaScript. LiveConnect was originally an integrated feature of both the Netscape Navigator browser and Netscape's server-side JavaScript. Now, it is a standalone library that can be embedded within other projects, such as the Mozilla browser. More information on LiveConnect can be found by searching the index on Netscape's DevEdge site.  This README assumes basic familiarity with JSRef, the reference implementation of JavaScript, and with the LiveConnect technology.

The JSRef project/makefiles (located in another directory) build a library or DLL containing the JavaScript runtime (compiler, interpreter, decompiler, garbage collector, atom manager, standard classes).  The LiveConnect project/makefiles build a library that links with both JSRef and any Java Virtual Machine (JVM) that implements the Java Native Interface (JNI), as specified by JavaSoft.  It then compiles a small "shell" example program and links that with the library to make an interpreter that can be used interactively and with test scripts.  See the sample shell interactions.

Scott Furman, 10/31/98

New features

The following features were not available in the versions of LiveConnect that were integrated with Netscape Navigator versions 4.x and earlier.  For information on LiveConnect version 1, which was used in Navigator versions 3 and 4, and Enterprise Server 3, see Netscape's DevEdge site or any number of 3rd-party publications.)

LiveConnect version 3 (8/31/99)

LiveConnect version 2 (7/31/98)

  • The Java methods of java.lang.Object are now invokeable methods of JavaArray objects, matching the behavior of arrays when accessed from Java.  (Java arrays are a subclass of java.lang.Object.) For example, Java's getClass() and hashCode() methods can now be called on JavaArray objects.  (In prior versions of LiveConnect, the methods of java.lang.Object were only inherited by non-array Java objects.)
  • Note that this change has caused the string representation of JavaArray objects to change.  Previously, the JavaArray toString() method always printed "[object JavaArray]" for all JavaArray's.  Now, the Java java.lang.Object.toString() method is called to convert JavaArray objects to strings, just as with other, non-array Java objects that are accessible via LiveConnect. java.lang.Object.toString()is defined in the Java Language Specification to return the value of the following expression:

    getClass().getName() + '@' + Integer.toHexString(hashCode())

     

  • A one-character string is now an acceptable match for an argument to a Java method of type char.  (In earlier versions of LiveConnect, the only acceptable match for a char had to be a JavaScript value that was convertible to a number.)  For example, the following is now possible:
  • c = new java.lang.Character("F")

     

  • A JavaClass object is now an acceptable match for an argument to a Java method of type java.lang.Class.  For example, you can now write:
  • java.lang.reflect.Array.newInstance(java.lang.String, 3)

    instead of the more verbose:

    jls = java.lang.Class.forName("java.lang.String")
    java.lang.reflect.Array.newInstance(jls, 3)


     

    Compatibility

    Unlike this standalone/component release, all previous versions of LiveConnect appeared only as an integrated feature of Netscape Navigator or the Enterprise Server.  The variants of LiveConnect that appeared in Navigator versions 3.x and 4.x all behave much the same, modulo bugs.  For brevity we refer to this classic version of LiveConnect as "LC1" (LiveConnect version 1) and this most recent release as "LC3".  With a few exceptions LC3 provides a superset of LC1 features. (There was an intermediate LiveConnect release known as "LC2" in 7/98, but it was not used in any products.)

    Limitations/Bugs/To-Do

    Build conventions

    The following directions are for building the standalone version of LiveConnect. To build the version that's used in the Mozilla browser, see the Mozilla build documentation.

    On all platforms, you must update your JVM's CLASSPATH to point to the js/src/liveconnect/classes subdirectory.  If you do not, LiveConnect will still operate but with the limitation that JS objects may not be passed as arguments of Java methods and it will not be possible to call from Java into JavaScript, i.e. the netscape.javascript.JSObject class will be inaccessible.  Another downside of operating without these classes is that Java error messages will not include a Java stack trace, when one is available.  If your CLASSPATH is set improperly, you will see a message like, "initialization error: Can't load class netscape/javascript/JSObject" when starting a LiveConnect debug build.

    By default, all platforms build a version of LiveConnect that is not threadsafe.  If you require thread-safety, you must also populate the mozilla/dist directory with NSPR headers and libraries.  (NSPR implements a portable threading library, among other things.  The source is downloadable via CVS from mozilla/nsprpub.)  Next, you must define JS_THREADSAFE when building LiveConnect, either on the command-line (gmake/nmake) or in a universal header file.  Note that JSRef must also be built with JS_THREADSAFE.

    One important note about building on Windows: There are two independent build systems (in addition to the Mozilla browser build system). One of them uses the IDE project files and the other uses gmake and makefiles. The former will be preferred by most for debugging and the latter is more complete, since it builds the necessary Java classes in addition to compiling the LiveConnect C code.

    Naming and coding conventions:

    The LiveConnect API

    All public LiveConnect entry points and callbacks are documented in jsjava.h, the header file that exports those functions.
     

    File walk-through

     
    jsjava.h LiveConnect's only public header file.  Defines all public API entry points, callbacks and types. 
    jsj_private.h LiveConnect internal header file for intra-module sharing of functions and types.
    jsj.c Public LiveConnect API entry points and initialization code. Handling of multiple threads and multiple JVMs.
    jsj_array.c Read and write elements of a Java array, performing needed conversions to/from JS types.
    jsj_class.c Construct and manipulate JavaClassDescriptor structs, which are the native representation for Java classes.  JavaClassDescriptors are used to describe the methods and fields of a class, including their type signatures, and include a reference to the peer java.lang.Class object.  Since each Java object has a class, there is a JavaClassDescriptor associated with the JavaScript reflection of each Java Object.
    jsj_convert.c Convert between Java and JavaScript values of all types, which may require calling routines in other files to wrap JS objects as Java objects and vice-versa.
    jsj_field.c Reflect Java fields as properties of JavaObject objects and implement getter/setter access to those fields.
    jsj_JavaArray.c Implementation of the JavaScript JavaArray class.  Instances of JavaArray are used to reflect Java arrays.
    jsj_JavaClass.c Implementation of the JavaScript JavaClass class.   Instances of JavaClass are used to reflect Java classes.
    jsj_JavaObject.c Implementation of the JavaScript JavaObject class.   Instances of JavaObject are used to reflect Java objects, except for Java arrays, although some of the code in this file is used by the JavaArray code.
    jsj_JavaMember.c Implementation of the JavaScript JavaMember class.  JavaMember's are a strange beast required only to handle the special case of a public field and a public method that appear in the same Java class and which have the same name.
    jsj_JavaPackage.c Implementation of the JavaScript JavaPackage class.   Instances of JavaPackage are used to reflect Java packages.  The JS properties of a JavaPackage are either nested JavaPackage objects or a JavaClass object.
    jsj_JSObject.c Implementation of the native methods for the  netscape.javascript.JSObject Java class, which are used for calling into JavaScript from Java.  It also contains the code that wraps JS objects as instances of  netscape.javascript.JSObject and the code that handles propagation of exceptions both into and out of Java.
    jsj_method.c Reflect Java methods as properties of JavaObject objects and make it possible to invoke those methods.  Includes overloaded method resolution and argument/return-value conversion code.
    jsj_utils.c Low-level utility code for reporting errors, etc.

    Sample LiveConnect shell interactions

    Java packages, classes and constructors

    js> java
    [JavaPackage java]
    js> awt = java.awt
    [JavaPackage java.awt]
    js> Rectangle = awt.Rectangle
    [JavaClass java.awt.Rectangle]

    Java instance fields and methods

    js> r = new java.awt.Rectangle(34, 23)
    java.awt.Rectangle[x=0,y=0,width=34,height=23]
    js> r.width - r.height
    11
    js> r.x = 7; r.y = 4
    4
    js> r
    java.awt.Rectangle[x=7,y=4,width=34,height=23]
    js> r.grow(3)
    There is no Java method java.awt.Rectangle.grow that matches JavaScript argument types (number).
    Candidate methods with the same name are:
       void grow(int, int)

    js> r.grow(3, 3)
    js> r
    java.awt.Rectangle[x=4,y=1,width=40,height=29]

    Java arrays

    js> s = new java.lang.String("mastiff")
    mastiff
    js> c = s.toCharArray()
    [C@298e9b
    js> c[0] = "b"; c[4] = "a"; c[5] = "r"; c[6] = "d"
    d
    js> s2 = new java.lang.String(c)
    bastard

    Java static fields and methods

    js> java.lang.reflect.Modifier.ABSTRACT
    1024
    js> java.lang.Math.sin(3) + 2
    2.1411200080598674

    Explicit resolution of overloaded Java methods

    js> x = "23"
    23
    js> java.lang.Math.abs(x)
    The choice of static Java method java.lang.Math.abs matching JavaScript argument types (string) is ambiguous.
    Candidate methods are:
       long abs(long)
       float abs(float)
       double abs(double)
       int abs(int)
    js> abs = java.lang.Math["abs(int)"]

    function abs(int)() {
        [native code]
    }

    js> abs(x)
    23

    Public Method/field enumeration

    js> out = java.lang.System.out
    java.io.PrintStream@2980f5
    js> for (m in out) print(m)
    println
    print
    checkError
    close
    flush
    write
    wait
    notifyAll
    notify
    toString
    equals
    hashCode
    getClass
    js> for (m in java.lang.String) print(m)
    copyValueOf
    valueOf

    'instanceof' and 'in' operators

    js> s = new java.lang.String("foop")
    foop
    js> s instanceof java.lang.Class
    false
    js> s instanceof java.lang.Object
    true
    js> "valueOf" in s
    true
    js> "NoSuchThing" in s
    false

    Applying JavaScript string methods to Java strings

    js> s = new java.lang.String("The rain in Spain falls mainly on my head.")
    The rain in Spain falls mainly on my head.
    js> s.match(/Spain.*my/)
    Spain falls mainly on my

    Applying JavaScript array methods to Java arrays

    js> s = new java.lang.String("JavaScript")
    JavaScript
    js> c = s.toCharArray()
    [C@298aef
    js> c.reverse()
    [C@298aef
    js> new java.lang.String(c)
    tpircSavaJ