dynamically test jar availability?


    Jul 12 2006 | 3:07 am
    I have an mxj external that links against the apache commons net
    library. things work great when the jar file is present in the
    classpath, everything load and runs nicely. if I remove it from the
    path, max bombs when I try to load my object. I tried to safety-check
    it with the following code:
    try {
    Class.forName("org.apache.commons.net.telnet.TelnetClient");
    } catch (ClassNotFoundException ex) {
    bail("commons net lib not found");
    }
    // ok to use the loaded class
    tc = new TelnetClient();
    but the bail doesn't seem to be effective. if I duplicate that code
    into a command-line test project, the jvm doesn't lock up. if I
    comment out the new TelnetClient() completely, max still bombs. I
    guess because I've got a class variable that references it? I haven't
    tried stripping all that out as well, as that would break the object
    beyond usefulness.
    any ideas or suggestions?
    console.log:
    Exception in thread "AWT-AppKit" Exception in thread "AWT-AppKit"
    Exception in thread "AWT-AppKit" Jul 11 01:45:24 thrustty /Volumes/
    userdata/apps/audio/MaxMSP 4.5/MaxMSP 4.5.app: An unexpected Java
    error has been detected by HotSpot Virtual Machine.
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: If this error is reproducible, please report it with
    the following information:
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: 1. Provide the steps to reproduce, a test case, and
    any relevant information
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: 2. The corresponding
    JavaNativeCrash_pid.crash.log (Java state)
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: 3. The corresponding .crash.log (native
    state; generated by CrashReporter)
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: 4. This data:
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: Java VM: Java HotSpot(TM) Client VM
    (1.5.0_06-57 mixed mode)
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: Bus Error (0xa) at pc=0x05225c14
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: Process ID: 1050, Current Thread: 25492480
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: File report at: http://bugreport.apple.com/
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: An error report file has been written to:
    Jul 11 01:45:24 thrustty /Volumes/userdata/apps/audio/MaxMSP 4.5/
    MaxMSP 4.5.app: /Volumes/userdata/users/thrust/Library/Logs/Java/
    JavaNativeCrash_pid1050.crash.log
    Jul 11 01:45:30 thrustty crashdump[1059]: MaxMSP 4.5.app crashed
    Jul 11 01:45:31 thrustty crashdump[1059]: crash report written to: /
    Volumes/userdata/users/thrust/Library/Logs/CrashReporter/MaxMSP
    4.5.app.crash.log
    ...
    JavaNativeCrash_pid1050.crash.log
    Local Time = Tue Jul 11 01:45:24 2006
    # This JavaNativeCrash log describes the Java state at a Native Crash
    in a Java application.
    # The corresponding native state can be found in the crash log
    generated by CrashReporter.
    # If this error is reproducible, please report it with the following
    information:
    # 1. Provide the steps to reproduce, a test case, and any relevant
    information
    # 2. This JavaNativeCrash_pid.crash.log (Java state)
    # 3. The corresponding .crash.log (native state; generated by
    CrashReporter)
    # File report at: http://bugreport.apple.com/
    # An unexpected Java error has been detected by HotSpot Virtual Machine:
    #
    # Java VM: Java HotSpot(TM) Client VM (1.5.0_06-57 mixed mode)
    #
    # Bus Error (0xa) at pc=0x05225c14, pid=1050, tid=25492480
    --------------- T H R E A D ---------------
    Current thread (0x053014e0): JavaThread "AWT-
    AppKit" [_thread_in_native, id=-1610551912]
    Stack: [0xbf800000,0xc0000000)
    --------------- P R O C E S S ---------------
    Java Threads: ( => current thread )
    0x0530d700 JavaThread "AWT-Shutdown" [_thread_blocked, id=25537024]
    0x0530a7c0 JavaThread "Low Memory Detector" daemon
    [_thread_blocked, id=25849344]
    0x05309e80 JavaThread "CompilerThread0" daemon [_thread_blocked,
    id=25860608]
    0x053099e0 JavaThread "Signal Dispatcher" daemon [_thread_blocked,
    id=25859584]
    0x05309710 JavaThread "Surrogate Locker Thread (CMS)" daemon
    [_thread_blocked, id=25866240]
    0x05308da0 JavaThread "Finalizer" daemon [_thread_blocked,
    id=25864192]
    0x053089c0 JavaThread "Reference Handler" daemon [_thread_blocked,
    id=25858560]
    =>0x053014e0 JavaThread "AWT-AppKit" [_thread_in_native, id=-1610551912]
    Other Threads:
    0x053081d0 VMThread [id=25539072]
    0x0530be80 WatcherThread [id=25850368]
    VM state:not at safepoint (normal execution)
    VM Mutex/Monitor currently owned by a thread: None
    Heap
    def new generation total 4032K, used 1268K [0x099e0000, 0x09de0000,
    0x09de0000)
    eden space 3968K, 31% used [0x099e0000, 0x09b1d3b8, 0x09dc0000)
    from space 64K, 0% used [0x09dd0000, 0x09dd0000, 0x09de0000)
    to space 64K, 0% used [0x09dc0000, 0x09dc0000, 0x09dd0000)
    concurrent mark-sweep generation total 12288K, used 265K [0x09de0000,
    0x0a9e0000, 0x199e0000)
    concurrent-mark-sweep perm gen total 8192K, used 2748K [0x199e0000,
    0x1a1e0000, 0x1d9e0000)
    Dynamic libraries and executable:
    [0x000019e0-0x000027f8] /System/Library/Frameworks/Carbon.framework/
    Versions/A/Support/LaunchCFMApp
    [0x908dbe74-0x908dbf44] /System/Library/Frameworks/
    CoreServices.framework/Versions/A/CoreServices
    [0x92f02e68-0x92f02f38] /System/Library/Frameworks/Carbon.framework/
    Versions/A/Carbon
    [0x947353a0-0x94962c40] /System/Library/Frameworks/
    QuickTime.framework/Versions/A/QuickTime
    ...
    max crash log:
    Host Name: thrustty
    Date/Time: 2006-07-11 01:45:24.504 -0300
    OS Version: 10.4.7 (Build 8J135)
    Report Version: 4
    Command: MaxMSP 4.5.app
    Path: /Volumes/userdata/apps/audio/MaxMSP 4.5/MaxMSP 4.5.app
    Parent: WindowServer [66]
    Version: 4.5.6 (4.5.6 - 27 October 2005)
    PID: 1050
    Thread: 0
    Exception: EXC_BAD_ACCESS (0x0001)
    Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000010
    Thread 0 Crashed:
    0 mxj[ 0x05225c14 construct + 256
    1 mxj[ 0x0522526c maxjava_new + 1368
    2 MaxPPC3.1pwpc 0x00436e00 typedmess_fun + 152
    3 MaxPPC3.1pwpc 0x005355a4 object_new_typed + 164
    4 MaxPPC3.1pwpc 0x00429738 auxtable_search + 156
    5 MaxPPC3.1pwpc 0x0042bc54 newload_internal + 64
    6 MaxPPC3.1pwpc 0x0042bbc8 newload + 52
    7 MaxPPC3.1pwpc 0x00436e00 typedmess_fun + 152
    8 MaxPPC3.1pwpc 0x00436ae8 typedmess + 92
    9 MaxPPC3.1pwpc 0x00438088 aeval + 1264
    10 MaxPPC3.1pwpc 0x0040bfe0 atombuf_eval + 156
    11 MaxPPC3.1pwpc 0x004d6708 patcher_vnewex + 160
    12 MaxPPC3.1pwpc 0x00436e30 typedmess_fun + 200
    13 MaxPPC3.1pwpc 0x00436ae8 typedmess + 92
    14 MaxPPC3.1pwpc 0x00438088 aeval + 1264
    15 MaxPPC3.1pwpc 0x004109d8 bf_fastload + 692
    16 MaxPPC3.1pwpc 0x0042a940
    lowload_type__FPcslsP4atoms + 500
    17 MaxPPC3.1pwpc 0x0042b414 fileload_extended + 176
    18 MaxPPC3.1pwpc 0x0042b330 fileload_type + 68
    19 MaxPPC3.1pwpc 0x0042ae60 dropload + 404
    20 MaxPPC3.1pwpc 0x00409a90 ae_openfile__FP6FSSpec
    + 28
    21 MaxPPC3.1pwpc 0x004ecdb4 sysiac_iterate + 264
    22 MaxPPC3.1pwpc 0x00409c4c ae_docopen + 44
    23 com.apple.AE 0x914f8960 aeDispatchAppleEvent
    (AEDesc const*, AEDesc*, unsigned long, unsigned char*) + 208
    24 com.apple.AE 0x914f87fc
    dispatchEventAndSendReply(AEDesc const*, AEDesc*) + 44
    25 com.apple.AE 0x914f8654 aeProcessAppleEvent + 284
    26 com.apple.HIToolbox 0x931e8eb0 AEProcessAppleEvent + 60
    27 com.apple.HIToolbox 0x9322cb24 ProcessHighLevelEvent
    + 140
    28 com.apple.HIToolbox 0x9322ca7c
    StandardApplicationEventHandler(OpaqueEventHandlerCallRef*,
    OpaqueEventRef*, void*) + 328
    29 com.apple.HIToolbox 0x931e5554 DispatchEventToHandlers
    (EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 692
    30 com.apple.HIToolbox 0x931e4cac
    SendEventToEventTargetInternal(OpaqueEventRef*,
    OpaqueEventTargetRef*, HandlerCallRec*) + 372
    31 com.apple.HIToolbox 0x931e4b28
    SendEventToEventTargetWithOptions + 40
    32 com.apple.HIToolbox 0x931ebe9c
    ToolboxEventDispatcherHandler(OpaqueEventHandlerCallRef*,
    OpaqueEventRef*, void*) + 704
    33 com.apple.HIToolbox 0x931e57a4 DispatchEventToHandlers
    (EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 1284
    34 com.apple.HIToolbox 0x931e4cac
    SendEventToEventTargetInternal(OpaqueEventRef*,
    OpaqueEventTargetRef*, HandlerCallRec*) + 372
    35 com.apple.HIToolbox 0x931eba60 SendEventToEventTarget
    + 40
    36 com.apple.HIToolbox 0x9322c7a0 ToolboxEventDispatcher
    + 92
    37 com.apple.HIToolbox 0x9322c72c HLTBEventDispatcher + 16
    38 com.apple.HIToolbox 0x9322ace4
    RunApplicationEventLoop + 148
    39 MaxPPC3.1pwpc 0x0042d4fc app_run + 48
    40 MaxPPC3.1pwpc 0x0042c2e0 main + 796
    ...

    • Jul 12 2006 | 10:18 am
      On 12 Jul 2006, at 05:07, ritchie wrote:
      > if I remove it from the path, max bombs when I try to load my object.
      For what it's worth, it looks like a fault in the JVM, not in Max.
      Your code looks fine... However, perhaps you're getting the wrong
      class loader? MXJClassLoader.getInstance() will get you a/the MXJ
      class loader (although I thought there were two: one static, one
      dynamic?).
      nick rothwell -- composition, systems, performance -- http://
      www.cassiel.com
    • Jul 12 2006 | 4:09 pm
      On 06-07-12, at 0718, Nick Rothwell wrote:
      >
      > For what it's worth, it looks like a fault in the JVM, not in Max.
      > Your code looks fine... However, perhaps you're getting the wrong
      > class loader? MXJClassLoader.getInstance() will get you a/the MXJ
      > class loader (although I thought there were two: one static, one
      > dynamic?).
      >
      ok, I've narrowed it down a little. using MXJClassLoader.getInstance
      ().getClazz() behaves the same as Class.forName() - it detects that
      the class isn't present. the problem seems to be how threading is
      handled, though I'm not sure I fully understand it. I've included
      code for a minimal test case.
      compile all three files, and run TestLoader from the commandline and
      TestMaxLoader from max. you can send "test" to the mxj object if you
      like, it doesn't really matter. then quit max and delete
      MissingClass.class, and re-run the above test. when you try to
      instantiate [mxj TestMaxLoader] max bombs, you don't even get a
      chance to press 'test'. running at the command line doesn't crash at
      all, and the thread prints out "no class found" as expected.
      given that things work fine outside max, I'm a little suspicious that
      this problem is entirely within the jvm, but I will gather up the
      crashlogs and send them in to apple. if you can't reproduce the
      problem I can send crashlogs to the list as well. I'm running
      os10.4.7, max4.5.7 and java1.5.0_06 on ppc.
      // TestMaxLoader.java
      import com.cycling74.max.MaxObject;
      public class TestMaxLoader extends MaxObject {
      private volatile MissingClass mc = null;
      public TestMaxLoader() {
      System.out.println("searching for MissingClass");
      try {
      Class.forName("MissingClass");
      } catch (ClassNotFoundException ex) {
      System.out.println("MissingClass not found");
      return;
      }
      // use the loaded class
      mc = new MissingClass();
      }
      public void test() {
      new Thread() {
      public void run() {
      try {
      System.out.println("the class says: " + mc.test());
      } catch (NoClassDefFoundError e) {
      System.out.println("no class found");
      }
      }
      }.start();
      }
      }
      // TestLoader.java
      public class TestLoader {
      private volatile MissingClass mc = null;
      public TestLoader() {
      System.out.println("searching for MissingClass");
      try {
      Class.forName("MissingClass");
      } catch (ClassNotFoundException ex) {
      System.out.println("MissingClass not found");
      return;
      }
      // use the loaded class
      mc = new MissingClass();
      }
      public void test() {
      new Thread() {
      public void run() {
      try {
      System.out.println("the class says: " + mc.test());
      } catch (NoClassDefFoundError e) {
      System.out.println("no class found");
      }
      }
      }.start();
      }
      public static void main(String args[]) {
      TestLoader tr = new TestLoader();
      tr.test();
      }
      }
      // MissingClass.java
      public class MissingClass {
      public String test() {
      return "it works!";
      }
      }
    • Jul 12 2006 | 5:35 pm
      On 06-07-12, at 1309, ritchie wrote:
      >
      > given that things work fine outside max, I'm a little suspicious
      > that this problem is entirely within the jvm, but I will gather up
      > the crashlogs and send them in to apple. if you can't reproduce the
      > problem I can send crashlogs to the list as well. I'm running
      > os10.4.7, max4.5.7 and java1.5.0_06 on ppc.
      >
      little more: it bombs max4.5.7 on windows xp running java1.5.0_07,
      and max4.6b11 with java1.5.0_06 on os10.4.7.
      the command-line test app also works fine on windows.
      best regards,
      r.
    • Jul 12 2006 | 6:55 pm
      Ill look into this today and see if I can reproduce and further
      enlighten.
      topher
      On Jul 12, 2006, at 09:09 AM, ritchie wrote:
      > On 06-07-12, at 0718, Nick Rothwell wrote:
      >>
      >> For what it's worth, it looks like a fault in the JVM, not in Max.
      >> Your code looks fine... However, perhaps you're getting the wrong
      >> class loader? MXJClassLoader.getInstance() will get you a/the MXJ
      >> class loader (although I thought there were two: one static, one
      >> dynamic?).
      >>
      > ok, I've narrowed it down a little. using MXJClassLoader.getInstance
      > ().getClazz() behaves the same as Class.forName() - it detects that
      > the class isn't present. the problem seems to be how threading is
      > handled, though I'm not sure I fully understand it. I've included
      > code for a minimal test case.
      >
      > compile all three files, and run TestLoader from the commandline
      > and TestMaxLoader from max. you can send "test" to the mxj object
      > if you like, it doesn't really matter. then quit max and delete
      > MissingClass.class, and re-run the above test. when you try to
      > instantiate [mxj TestMaxLoader] max bombs, you don't even get a
      > chance to press 'test'. running at the command line doesn't crash
      > at all, and the thread prints out "no class found" as expected.
      >
      > given that things work fine outside max, I'm a little suspicious
      > that this problem is entirely within the jvm, but I will gather up
      > the crashlogs and send them in to apple. if you can't reproduce the
      > problem I can send crashlogs to the list as well. I'm running
      > os10.4.7, max4.5.7 and java1.5.0_06 on ppc.
      >
      > // TestMaxLoader.java
      > import com.cycling74.max.MaxObject;
      >
      > public class TestMaxLoader extends MaxObject {
      > private volatile MissingClass mc = null;
      >
      > public TestMaxLoader() {
      > System.out.println("searching for MissingClass");
      > try {
      > Class.forName("MissingClass");
      > } catch (ClassNotFoundException ex) {
      > System.out.println("MissingClass not found");
      > return;
      > }
      > // use the loaded class
      > mc = new MissingClass();
      > }
      >
      > public void test() {
      > new Thread() {
      > public void run() {
      > try {
      > System.out.println("the class says: " + mc.test());
      > } catch (NoClassDefFoundError e) {
      > System.out.println("no class found");
      > }
      > }
      > }.start();
      > }
      > }
      >
      >
      > // TestLoader.java
      > public class TestLoader {
      > private volatile MissingClass mc = null;
      >
      > public TestLoader() {
      > System.out.println("searching for MissingClass");
      > try {
      > Class.forName("MissingClass");
      > } catch (ClassNotFoundException ex) {
      > System.out.println("MissingClass not found");
      > return;
      > }
      > // use the loaded class
      > mc = new MissingClass();
      > }
      >
      > public void test() {
      > new Thread() {
      > public void run() {
      > try {
      > System.out.println("the class says: " + mc.test());
      > } catch (NoClassDefFoundError e) {
      > System.out.println("no class found");
      > }
      > }
      > }.start();
      > }
      >
      > public static void main(String args[]) {
      > TestLoader tr = new TestLoader();
      > tr.test();
      > }
      > }
      >
      >
      > // MissingClass.java
      > public class MissingClass {
      > public String test() {
      > return "it works!";
      > }
      > }
      >
    • Jul 14 2006 | 2:00 pm
      On 06-07-12, at 1557, topher lafata wrote:
      > Ill look into this today and see if I can reproduce and further
      > enlighten.
      >
      hey topher, it looks like it's choking on anonymous inner classes. if
      I re-write so it doesn't generate a TestMaxLoader$1.class file,
      things work ok. uncomment the anonymous thread and it crashes. I
      presume this doesn't have anything to do with threading, and the test
      case can likely be shrunk to just use anonymous inner classes.
      best,
      r.
      // TestMaxLoader.java
      import com.cycling74.max.MaxObject;
      public class TestMaxLoader extends MaxObject implements Runnable {
      private MissingClass mc = null;
      public TestMaxLoader() {
      System.out.println("searching for MissingClass");
      try {
      Class.forName("MissingClass");
      } catch (ClassNotFoundException ex) {
      System.out.println("MissingClass not found");
      return;
      }
      // use the loaded class
      mc = new MissingClass();
      }
      public void test() {
      // new Thread() {
      // public void run() {
      // try {
      // System.out.println("anon.run(): " + mc.test());
      // } catch (NoClassDefFoundError e) {
      // System.out.println("anon.run(): no class found");
      // }
      // }
      // }.start();
      new Thread(this).start();
      }
      public void run() {
      try {
      System.out.println("TestMaxLoader.run(): " + mc.test());
      } catch (NoClassDefFoundError e) {
      System.out.println("TestMaxLoader.run(): no class found");
      }
      }
      }
    • Jul 14 2006 | 8:06 pm
      I have been looking into it as well and something weird is definitely
      going on.
      I havent been able to pinpoint it yet. Thanks for the additional info.
      Topher
      On Jul 14, 2006, at 07:00 AM, ritchie wrote:
      > On 06-07-12, at 1557, topher lafata wrote:
      >> Ill look into this today and see if I can reproduce and further
      >> enlighten.
      >>
      > hey topher, it looks like it's choking on anonymous inner classes.
      > if I re-write so it doesn't generate a TestMaxLoader$1.class file,
      > things work ok. uncomment the anonymous thread and it crashes. I
      > presume this doesn't have anything to do with threading, and the
      > test case can likely be shrunk to just use anonymous inner classes.
      >
      > best,
      > r.
      >
      >
      >
      > // TestMaxLoader.java
      > import com.cycling74.max.MaxObject;
      >
      > public class TestMaxLoader extends MaxObject implements Runnable {
      > private MissingClass mc = null;
      >
      > public TestMaxLoader() {
      > System.out.println("searching for MissingClass");
      > try {
      > Class.forName("MissingClass");
      > } catch (ClassNotFoundException ex) {
      > System.out.println("MissingClass not found");
      > return;
      > }
      > // use the loaded class
      > mc = new MissingClass();
      > }
      >
      > public void test() {
      > // new Thread() {
      > // public void run() {
      > // try {
      > // System.out.println("anon.run(): " + mc.test());
      > // } catch (NoClassDefFoundError e) {
      > // System.out.println("anon.run(): no class found");
      > // }
      > // }
      > // }.start();
      >
      > new Thread(this).start();
      > }
      >
      > public void run() {
      > try {
      > System.out.println("TestMaxLoader.run(): " + mc.test());
      > } catch (NoClassDefFoundError e) {
      > System.out.println("TestMaxLoader.run(): no class found");
      > }
      > }
      > }
      >