Troubleshooting Tcl Blend

Problems Starting Tcl Blend

Problems Starting in General

A little background on how Tcl Blend starts might help debug start up problems.

Tcl Blend uses Tcl's package system to load in a shared library (or dll) that contains the C side of the Tcl/Java interface. The shared library starts up the Java Virtual machine and loads in the Java classes that implement the Java side of Tcl Blend.

When you type package require java, the package system reads each element of the auto_path Tcl list to get a directory name. The directory and any immediate subdirectories are searched for pkgIndex.tcl files. For more information, see the Tcl package and tclvars manual pages

A typical pkgIndex.tcl file includes Tcl commands that do package specific setup and then package provide is called, which tells the Tcl package system that a certain version of the package is available.

In Tcl Blend, the pkgIndex.tcl file usually resides in the same directory as the libtclblend.so shared library and the tclblend.jar Java class archive file.

pkgIndex.tcl contains commands that set the CLASSPATH environment variable to include the current directory, so that the Java Virtual Machine will find the Java classes that implement the Java side of the Tcl Blend interface.

pkgIndex.tcl then uses the Tcl load command to load the Tcl Blend shared library. The Tcl load command is fairly platform specific. Under Solaris, the is called libtclblend.so and your LD_LIBRARY_PATH environment variable is used to find the library. Under Windows, the library is called tclblend.dll, your current directory is searched first and then the PATH environment variable is searched.

Problems Starting Under Windows

Tcl Blend 1.0 fails to install under Tcl 8.0.3

Under Windows, the Tcl Blend 1.0 prebuilt binaries fail to install on a machine that only has Tcl8.0.3 installed.
The installer comes up with a message about how Tcl8.0 is not installed.
The workaround is to install Tcl8.0, then install Tcl Blend, and then Install Tcl8.0.3
Another minor nit is that the Add/Remove program window says 'Tcl 8.0 for Windows' for both Tcl8.0 and Tcl8.0.3
The dynamic link library javai.dll could not be found in the specified path
If you are running Tcl Blend 1.0, then the solution here is to be sure that you have Sun's JDK1.1.x installed and that the directory that contains javai.dll is in your path.
If the JDK is installed at c:\jdk1.1.6, then be sure that c:\jdk1.1.6\bin is in your path.
Under NT to adjust your path, go to the NT Start menu, choose Settings, then Control Panel, then choose the System Icon. In the System window, choose the Environment tab and look under the System Variables section for the Path entry. Add c:\jdk1.1.6\bin to the value of the path and click Set, then OK.
If you are running Tcl Blend 1.1, then the problem could be that you don't have Java installed, Java is not in your path, or you installed the JDK1.1 Tcl Blend 1.0 binaries, but you are running JDK1.2 on your machine and JDK1.1 is not present or in your path.
I compiled my own Tcl8.0.3 from sources, and package require java fails to find the java package

If, under Windows, you compile and install Tcl8.0.3 yourself instead of using the prebuilt binaries from Scriptics or the Tcl Blast CD, then package require java may fail to find the java package. The problem is that if you install Tcl8.0.3 yourself, then the Software\Scriptics\Tcl Registry key is not set, so auto_path is not set to include the C:\Program Files\Tcl\lib directory, instead it only includes C:\Program Files\Tcl\lib\tcl8.0.

If the Tcl Blend1.1 pkgIndex.tcl file is in C:\Program Files\Tcl\lib\tclblend1.1, then as a workaround, you can append the parent directory to auto_path:

    lappend auto_path "C:/Program Files/Tcl/lib"
    package require java
Another workaround is to set the TCLLIBPATH environment variable to C:\Program Files\Tcl\lib.

The problem stems from a bug in tcl8.0.3/library/init.tcl, and the bug has been fixed in the CVS sources at Scriptics.

Problems Starting under Solaris

could not find class tcl/lang/Interp.
The LD_LIBRARY_PATH variable needs to be set to include the directory where your libtclblend.so file resides.
In your ~/.cshrc, you would do something like:
setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/usr/local/lib/tcl/tclblend

Also, check that libtclblend.so is in a directory listed in your auto_path Tcl variable.

Platform independent things to try.

  • If all else fails and package require java is failing, you may want to find look at the value of the auto_path Tcl variable and find the the Tcl Blend pkgIndex.tcl file that is being sourced and add debugging statements to that file. You may want to check the following:
  • Be sure that the Tcl Blend pkgIndex.tcl file that you think is being called is actually being called
  • Check the values of CLASSPATH and auto_path.
  • Calling the load command directly while in the directory that contains the Tcl Blend shared library and tclblend.jar can be useful. For the load command to work CLASSPATH needs to be set to include the current directory and the JDK's classes.zip

    Under Solaris, set LD_LIBRARY_PATH to . and to the JDK's native_threads directory.

    Below is a sample run that used JDK1.1.6.

    cxh@carson 133% ls
    libtclblend.so*	pkgIndex.tcl	tclblend.jar
    cxh@carson 134% setenv LD_LIBRARY_PATH .:/usr/java/lib/sparc/native_threads
    cxh@carson 135% setenv CLASSPATH `pwd`/tclblend.jar:/usr/java/lib/classes.zip
    cxh@carson 136% tclsh
    % load libtclblend.so
    % java::call System getProperty "java.version"
    1.1.6
    % 
    

  • Debugging Tcl Blend Usage problems

    Below are some hints to help debug Tcl Blend problems while developing code

    Tcl Problems

    tcl_traceExec

    To debug problems on the Tcl side, you may want to try setting the tcl_traceExec variable to 1, 2, or 3 to get tracing information about what commands the Tcl interpreter is running. The Tcl tclvars man page contains further information about tcl_traceExec

    Java Problems

    Version information

    If you have multiple JDKs installed, you may be accessing the wrong JDK. See JVM Information for Tcl commands that will access the JDK information, such as the JVM version or the CLASSPATH.

    Java Stacktraces

    See Tcl Blend Exceptions for information on how to print the Java stack after getting a Java exception.

    truss

    Under Solaris, you may find it useful to use the truss command to see what system calls tclsh is making. The output of truss can be voluminous, but sometimes it is the only way to track down path problems

    If you are running Tcl Blend 1.1 and JDK1.2, then you can set the tclblend_init variable to tell the JDK to go into verbose mode.

    The follow command will cause the JDK to print information about what classes are being loaded, and what the JNI is doing:

    set tclblend_init "-verbose:jni,class"
    package require java
    
    To see what sort of strings you can pass, type java -help and java -X.

    If you set tclblend_init to help, then a short help message is returned.

    Note that this functionality is only available with Tcl Blend 1.1 and JDK1.2

    Tracing Instructions

    The java.lang.Runtime optionally includes support for tracing instructions

    To turn on tracing, execute the following code:

        set runtime [java::call Runtime getRuntime]
        $runtime traceInstructions True
    
    For example:
    % package require java
    1.1
    % set runtime [java::call Runtime getRuntime]
    java0x1
    % $runtime traceInstructions True
    % set a [java::new java.util.GregorianCalendar]
    ED6660B0        0execute_java_constructor new tcl/lang/JavaNewCmd => tcl.lang.JavaNewCmd@ED66B748/ED757DC0
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B738/ED757DE0
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B720/ED757E40
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B710/ED757E80
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B838/ED757EC0
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B6F0/ED757F18
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B970/ED758008
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B948/ED7580B8
    ED6660B0        0execute_java_constructor new java/lang/String => java.lang.String@ED66B920/ED758140
    [etc]
    
    To turn of tracing of instructions, execute the following code:
        $runtime traceInstructions False
    
    The output of tracing instructions is very detailed, you may want to trace method calls instead.

    Tracing MethodCalls

    The java.lang.Runtime optionally includes support for tracing Java Method Calls

    To turn on tracing, execute the following code:

        set runtime [java::call Runtime getRuntime]
        $runtime traceMethodCalls True
    
    For example:
    % package require java
    1.1
    % set runtime [java::call Runtime getRuntime]
    java0x1
    %  $runtime traceMethodCalls True
    # main [ 1] | < java/lang/Runtime.traceMethodCalls(Z)V returning
    # main [ 1] | < tcl/lang/Interp.setResult(Ltcl/lang/TclObject;)V returning
    % set a [java::new java.util.GregorianCalendar]
    # main [ 1] | < tcl/lang/CObject.incrRefCount(J)V returning
    # main [ 1] | < tcl/lang/CObject.incrRefCount(J)V returning
    # main [ 1] | < tcl/lang/CObject.getString(J)Ljava/lang/String; returning
    # main [ 1] | < tcl/lang/Interp.createCommand(Ljava/lang/String;Ltcl/lang/Command;)V returning
    # main [ 1] | < tcl/lang/TclList.listLength(JJ)I returning
    # main [ 1] | < tcl/lang/CObject.incrRefCount(J)V returning
    # main [ 1] | < tcl/lang/CObject.decrRefCount(J)V returning
    # main [ 1] | < tcl/lang/TclList.listLength(JJ)I returning
    # main [ 2] | | < tcl/lang/CObject.incrRefCount(J)V returning
    # main [ 1] | < tcl/lang/TclList.index(JI)Ltcl/lang/TclObject; returning
    # main [ 1] | < tcl/lang/CObject.getString(J)Ljava/lang/String; returning
    # main [ 1] | < tcl/lang/TclList.listLength(JJ)I returning
    # main [ 2] | | < tcl/lang/CObject.incrRefCount(J)V returning
    # main [ 1] | < tcl/lang/TclList.index(JI)Ltcl/lang/TclObject; returning
    # main [ 1] | < tcl/lang/CObject.getString(J)Ljava/lang/String; returning
    # main [ 1] | < tcl/lang/Interp.getVar(Ljava/lang/String;Ljava/lang/String;I)Ltcl/lang/TclObject; throwing tcl/lang/TclException
    # main [ 1] | < tcl/lang/CObject.getString(J)Ljava/lang/String; returning
    # main [ 1] | < tcl/lang/CObject.makeRef(JLtcl/lang/TclObject;)V returning
    # main [ 1] | < tcl/lang/CObject.decrRefCount(J)V returning
    # main [ 3] | | | < java/lang/System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V returning
    # main [ 3] | | | < java/lang/Float.floatToIntBits(F)I returning
    # main [ 3] | | | < java/lang/Double.doubleToLongBits(D)J returning
    # main [ 1] | < tcl/lang/Interp.createCommand(Ljava/lang/String;Ltcl/lang/Command;)V returning
    # main [ 1] | < tcl/lang/Interp.setResult(Ltcl/lang/TclObject;)V returning
    java0x2
    % 
    
    To turn off tracing of method calls
        $runtime traceMethodCalls False
    

    Java Resources on the net

  • www.javasoft.com
  • Java Developers Connection: http://www.javasoft.com/jdc - This is free to join, and a good place to search for information about JNI bugs.
  • JDK1.2 JNI Enhancements: http://java.sun.com/products/jdk/1.2/docs/guide/jni/index.html - Includes the JNI1.1 Specification and a FAQ
  • Javasoft JNI Tutorial http://www.javasoft.com/docs/books/tutorial/native1.1/index.html
  • Scriptics Jacl and Tcl Blend Docs

  • Last updated: 10/09/05 cxh at eecs