Menu

#47 ReflectObject loses command

open
nobody
None
5
2008-08-25
2008-08-25
No

There seems to be a situation where a Java Object command is
deleted from the interpreter, but the object still resides
in the interp.reflectObjTable. This patch causes the
java object command to be re-created if the command no
longer exists.

Note that this bug is exposed when using Incr Tcl, I'm not sure
if there are other cases where the bug is exposed.

Also note: my first attempt at a patch simply invoked
interp.createCommand() if the command was missing, but
that yielded "reflected object is no longer valid" when used (from the
cmdProc() method.)

---------------------------------------------------------------------------------

IncrTcl method that exposes the bug, part of Aejaks 'Table' class.
(The ::Label constructor '-from $c' wraps up an existing Java
object, rather than creating a new one.)

----------------------------------------------------------------------------------

public method setCellLabelAttrs {columnIdx rowNum args} {
if {[catch {
set c [::java::cast [::Label::_getObjType_] [$_obj_ -noconvert getCellComponent $columnIdx $rowNum]]
puts "getCellComponent return object $c"
puts "check for command defined: [info commands $c]"

set label [::Label #auto -from $c]
} result]} {
error "invalid column or row, or cell component is not a Label: $result"
}
set result ""
set rc [catch {eval $label configure $args} result]
::itcl::delete object $label
if {$rc} {
error $result
} else {
return $result
}
}

----------------------------------------------------------------------------------

Test case, first time works; second time through, the java object command is
missing. This example creates a table with one row and two columns.
Invoking the 'setCellLabelAttrs' method changes the foreground color and text
of the Label in the first column. The first invocation works (setting the
text as 'RED' and changes its color to red.) The second invocation fails,
as the java object command no longer exists. The error raised is a result
of the 'from $c' missing the java object command.
----------------------------------------------------------------------------------
% Table .t -columns 2
% Pack .t
% .t insertRow 0 {first second}
% .t setCellLabelAttrs 0 0 -foreground red -text RED
%
getCellComponent return object java0x66
check for command defined: java0x66

% .t setCellLabelAttrs 0 0 -foreground blue -text BLUE
%
getCellComponent return object java0x66
check for command defined:
invalid column or row, or cell component is not a Label: unknown option "-from"

Discussion

  • Tom Poindexter

    Tom Poindexter - 2008-08-25

    Logged In: YES
    user_id=62910
    Originator: YES

    can't seem to attach a file, so here is the patch.

    diff -r -u tcljava/src/tcljava/tcl/lang/ReflectObject.java tcljava.ae/src/tcljava/tcl/lang/ReflectObject.java
    --- tcljava/src/tcljava/tcl/lang/ReflectObject.java 2006-04-13 01:36:50.000000000 -0600
    +++ tcljava.ae/src/tcljava/tcl/lang/ReflectObject.java 2008-08-23 14:40:00.000000000 -0600
    @@ -521,7 +521,13 @@
    System.out.println("incr useCount of found object " + roRep.refID + " to " + roRep.useCount);
    }

    - return roRep;
    + // make sure command still exists, if not, create it
    + if (interp.getCommand(roRep.refID) == null) {
    + roRep.isValid = true;
    + interp.createCommand(roRep.refID, roRep);
    + }
    +
    + return roRep;
    } else {
    if (cl.isArray()) {
    roRep = new ArrayObject();

     
  • Mo DeJong

    Mo DeJong - 2009-02-03

    package require java

    # Create table, add StringBuffer to the table

    set table [java::new java.util.HashMap]
    set key_obj [java::new String fookey]
    set value_obj [java::new java.lang.StringBuffer fooval]
    $table put $key_obj $value_obj

    # Lookup the Java object in the table, this will return
    # a new ref since the return type of the method is
    # Object but the original reflected type was StringBuffer.

    set lookup_ref [$table get $key_obj]
    set cmd "rename $lookup_ref {}"

    # Evaluate this command to delete the Tcl command for
    # the Java object currently reflected in lookup_ref.
    eval $cmd

    # Now query the Java object in the table, this must
    # not return the now stale ref currently contained
    # in value_obj.

    set new_ref [$table get $key_obj]

    # This command will fail if an invalid ref was returned
    $new_ref toString

     
  • Mo DeJong

    Mo DeJong - 2009-02-03

    package require java

    # Create table, add StringBuffer to the table

    set table [java::new java.util.HashMap]
    set key_obj [java::new String fookey]
    set value_obj [java::new java.lang.StringBuffer fooval]
    $table put $key_obj $value_obj

    # Lookup the Java object in the table, this will return
    # a new ref since the return type of the method is
    # Object but the original reflected type was StringBuffer.

    set lookup_ref [$table get $key_obj]
    set cmd "rename $lookup_ref {}"

    # Evaluate this command to delete the Tcl command for
    # the Java object currently reflected in lookup_ref.
    eval $cmd

    # Now query the Java object in the table, this must
    # not return the now stale ref currently contained
    # in value_obj.

    set new_ref [$table get $key_obj]

    # This command will fail if an invalid ref was returned
    $new_ref toString

     
  • Tom Poindexter

    Tom Poindexter - 2009-03-19

    File Added: tcljava.reflectobject.patch

     
  • Tom Poindexter

    Tom Poindexter - 2009-03-19

    Another possible patch

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.