Example #1
0
 // TODO: This may be called more than one time per error in the VM,
 // presumably because exceptions might be wrapped inside others,
 // and this will fire for both.
 protected void reportException(String message, ObjectReference or, ThreadReference thread) {
   listener.statusError(findException(message, or, thread));
 }
Example #2
0
  /**
   * Move through a list of stack frames, searching for references to code found in the current
   * sketch. Return with a RunnerException that contains the location of the error, or if nothing is
   * found, just return with a RunnerException that wraps the error message itself.
   */
  protected SketchException findException(
      String message, ObjectReference or, ThreadReference thread) {
    try {
      // use to dump the stack for debugging
      //      for (StackFrame frame : thread.frames()) {
      //        System.out.println("frame: " + frame);
      //      }

      List<StackFrame> frames = thread.frames();
      for (StackFrame frame : frames) {
        try {
          Location location = frame.location();
          String filename = null;
          filename = location.sourceName();
          int lineNumber = location.lineNumber() - 1;
          SketchException rex = build.placeException(message, filename, lineNumber);
          if (rex != null) {
            return rex;
          }
        } catch (AbsentInformationException e) {
          // Any of the thread.blah() methods can throw an AbsentInformationEx
          // if that bit of data is missing. If so, just write out the error
          // message to the console.
          // e.printStackTrace();  // not useful
          exception = new SketchException(message);
          exception.hideStackTrace();
          listener.statusError(exception);
        }
      }
    } catch (IncompatibleThreadStateException e) {
      // This shouldn't happen, but if it does, print the exception in case
      // it's something that needs to be debugged separately.
      e.printStackTrace();
    }
    // before giving up, try to extract from the throwable object itself
    // since sometimes exceptions are re-thrown from a different context
    try {
      // assume object reference is Throwable, get stack trace
      Method method =
          ((ClassType) or.referenceType())
              .concreteMethodByName("getStackTrace", "()[Ljava/lang/StackTraceElement;");
      ArrayReference result =
          (ArrayReference)
              or.invokeMethod(
                  thread, method, new ArrayList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);
      // iterate through stack frames and pull filename and line number for each
      for (Value val : result.getValues()) {
        ObjectReference ref = (ObjectReference) val;
        method =
            ((ClassType) ref.referenceType())
                .concreteMethodByName("getFileName", "()Ljava/lang/String;");
        StringReference strref =
            (StringReference)
                ref.invokeMethod(
                    thread, method, new ArrayList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);
        String filename = strref == null ? "Unknown Source" : strref.value();
        method = ((ClassType) ref.referenceType()).concreteMethodByName("getLineNumber", "()I");
        IntegerValue intval =
            (IntegerValue)
                ref.invokeMethod(
                    thread, method, new ArrayList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);
        int lineNumber = intval.intValue() - 1;
        SketchException rex = build.placeException(message, filename, lineNumber);
        if (rex != null) {
          return rex;
        }
      }
      //      for (Method m : ((ClassType) or.referenceType()).allMethods()) {
      //        System.out.println(m + " | " + m.signature() + " | " + m.genericSignature());
      //      }
      // Implemented for 2.0b9, writes a stack trace when there's an internal error inside core.
      method = ((ClassType) or.referenceType()).concreteMethodByName("printStackTrace", "()V");
      //      System.err.println("got method " + method);
      or.invokeMethod(
          thread, method, new ArrayList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);

    } catch (Exception e) {
      e.printStackTrace();
    }
    // Give up, nothing found inside the pile of stack frames
    SketchException rex = new SketchException(message);
    // exception is being created /here/, so stack trace is not useful
    rex.hideStackTrace();
    return rex;
  }
Example #3
0
  /**
   * Provide more useful explanations of common error messages, perhaps with a short message in the
   * status area, and (if necessary) a longer message in the console.
   *
   * @param exceptionClass Class name causing the error (with full package name)
   * @param message The message from the exception
   * @param listener The Editor or command line interface that's listening for errors
   * @return true if the error was purtified, false otherwise
   */
  public static boolean handleCommonErrors(
      final String exceptionClass, final String message, final RunnerListener listener) {
    if (exceptionClass.equals("java.lang.OutOfMemoryError")) {
      if (message.contains("exceeds VM budget")) {
        // TODO this is a kludge for Android, since there's no memory preference
        listener.statusError(
            "OutOfMemoryError: This code attempts to use more memory than available.");
        System.err.println(
            "An OutOfMemoryError means that your code is either using up too much memory");
        System.err.println(
            "because of a bug (e.g. creating an array that's too large, or unintentionally");
        System.err.println(
            "loading thousands of images), or simply that it's trying to use more memory");
        System.err.println("than what is supported by the current device.");
      } else {
        listener.statusError(
            "OutOfMemoryError: You may need to increase the memory setting in Preferences.");
        System.err.println(
            "An OutOfMemoryError means that your code is either using up too much memory");
        System.err.println(
            "because of a bug (e.g. creating an array that's too large, or unintentionally");
        System.err.println(
            "loading thousands of images), or that your sketch may need more memory to run.");
        System.err.println(
            "If your sketch uses a lot of memory (for instance if it loads a lot of data files)");
        System.err.println(
            "you can increase the memory available to your sketch using the Preferences window.");
      }
    } else if (exceptionClass.equals("java.lang.UnsatisfiedLinkError")) {
      listener.statusError("A library used by this sketch is not installed properly.");
      System.err.println("A library relies on native code that's not available.");
      System.err.println(
          "Or only works properly when the sketch is run as a "
              + ((Base.getNativeBits() == 32) ? "64-bit " : "32-bit ")
              + " application.");

    } else if (exceptionClass.equals("java.lang.StackOverflowError")) {
      listener.statusError("StackOverflowError: This sketch is attempting too much recursion.");
      System.err.println(
          "A StackOverflowError means that you have a bug that's causing a function");
      System.err.println("to be called recursively (it's calling itself and going in circles),");
      System.err.println("or you're intentionally calling a recursive function too much,");
      System.err.println("and your code should be rewritten in a more efficient manner.");

    } else if (exceptionClass.equals("java.lang.UnsupportedClassVersionError")) {
      listener.statusError(
          "UnsupportedClassVersionError: A library is using code compiled with an unsupported version of Java.");
      System.err.println(
          "This version of Processing only supports libraries and JAR files compiled for Java 1.6 or earlier.");
      System.err.println("A library used by this sketch was compiled for Java 1.7 or later, ");
      System.err.println("and needs to be recompiled to be compatible with Java 1.6.");

    } else if (exceptionClass.equals("java.lang.NoSuchMethodError")
        || exceptionClass.equals("java.lang.NoSuchFieldError")) {
      listener.statusError(
          exceptionClass.substring(10)
              + ": "
              + "You may be using a library that's incompatible "
              + "with this version of Processing.");
    } else {
      return false;
    }
    return true;
  }