alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (JavaExceptions.c)

This example Java source code file (JavaExceptions.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

checkedexceptionmapper, jni_false, jnienv, jvmti_error_circular_class_definition, jvmti_error_class_loader_unsupported, jvmti_error_fails_verification, jvmti_error_illegal_argument, jvmti_error_internal, jvmti_error_invalid_class, jvmti_error_null_pointer, jvmti_error_out_of_memory, jvmti_error_unmodifiable_class, jvmti_error_unsupported_redefinition_hierarchy_changed, null

The JavaExceptions.c Java example source code

/*
 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * Copyright 2003 Wily Technology, Inc.
 */

#include    <jni.h>
#include    <jvmti.h>

#include    "JPLISAssert.h"
#include    "Utilities.h"
#include    "JavaExceptions.h"

/**
 * This module contains utility routines for manipulating Java throwables
 * and JNIEnv throwable state from native code.
 */

static jthrowable   sFallbackInternalError  = NULL;

/*
 * Local forward declarations.
 */

/* insist on having a throwable. If we already have one, return it.
 * If not, map to fallback
 */
jthrowable
forceFallback(jthrowable potentialException);


jthrowable
forceFallback(jthrowable potentialException) {
    if ( potentialException == NULL ) {
        return sFallbackInternalError;
    }
    else {
        return potentialException;
    }
}

/**
 *  Returns true if it properly sets up a fallback exception
 */
jboolean
initializeFallbackError(JNIEnv* jnienv) {
    jplis_assert(isSafeForJNICalls(jnienv));
    sFallbackInternalError = createInternalError(jnienv, NULL);
    jplis_assert(isSafeForJNICalls(jnienv));
    return (sFallbackInternalError != NULL);
}


/*
 *  Map everything to InternalError.
 */
jthrowable
mapAllCheckedToInternalErrorMapper( JNIEnv *    jnienv,
                                    jthrowable  throwableToMap) {
    jthrowable  mappedThrowable = NULL;
    jstring     message         = NULL;

    jplis_assert(throwableToMap != NULL);
    jplis_assert(isSafeForJNICalls(jnienv));
    jplis_assert(!isUnchecked(jnienv, throwableToMap));

    message = getMessageFromThrowable(jnienv, throwableToMap);
    mappedThrowable = createInternalError(jnienv, message);

    jplis_assert(isSafeForJNICalls(jnienv));
    return mappedThrowable;
}


jboolean
checkForThrowable(  JNIEnv*     jnienv) {
    return (*jnienv)->ExceptionCheck(jnienv);
}

jboolean
isSafeForJNICalls(  JNIEnv * jnienv) {
    return !(*jnienv)->ExceptionCheck(jnienv);
}


void
logThrowable(   JNIEnv * jnienv) {
    if ( checkForThrowable(jnienv) ) {
        (*jnienv)->ExceptionDescribe(jnienv);
    }
}



/**
 *  Creates an exception or error with the fully qualified classname (ie java/lang/Error)
 *  and message passed to its constructor
 */
jthrowable
createThrowable(    JNIEnv *        jnienv,
                    const char *    className,
                    jstring         message) {
    jthrowable  exception           = NULL;
    jmethodID   constructor         = NULL;
    jclass      exceptionClass      = NULL;
    jboolean    errorOutstanding    = JNI_FALSE;

    jplis_assert(className != NULL);
    jplis_assert(isSafeForJNICalls(jnienv));

    /* create new VMError with message from exception */
    exceptionClass = (*jnienv)->FindClass(jnienv, className);
    errorOutstanding = checkForAndClearThrowable(jnienv);
    jplis_assert(!errorOutstanding);

    if (!errorOutstanding) {
        constructor = (*jnienv)->GetMethodID(   jnienv,
                                                exceptionClass,
                                                "<init>",
                                                "(Ljava/lang/String;)V");
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert(!errorOutstanding);
    }

    if (!errorOutstanding) {
        exception = (*jnienv)->NewObject(jnienv, exceptionClass, constructor, message);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert(!errorOutstanding);
    }

    jplis_assert(isSafeForJNICalls(jnienv));
    return exception;
}

jthrowable
createInternalError(JNIEnv * jnienv, jstring message) {
    return createThrowable( jnienv,
                            "java/lang/InternalError",
                            message);
}

jthrowable
createThrowableFromJVMTIErrorCode(JNIEnv * jnienv, jvmtiError errorCode) {
    const char * throwableClassName = NULL;
    const char * message            = NULL;
    jstring messageString           = NULL;

    switch ( errorCode ) {
        case JVMTI_ERROR_NULL_POINTER:
                throwableClassName = "java/lang/NullPointerException";
                break;

        case JVMTI_ERROR_ILLEGAL_ARGUMENT:
                throwableClassName = "java/lang/IllegalArgumentException";
                break;

        case JVMTI_ERROR_OUT_OF_MEMORY:
                throwableClassName = "java/lang/OutOfMemoryError";
                break;

        case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION:
                throwableClassName = "java/lang/ClassCircularityError";
                break;

        case JVMTI_ERROR_FAILS_VERIFICATION:
                throwableClassName = "java/lang/VerifyError";
                break;

        case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "class redefinition failed: attempted to add a method";
                break;

        case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "class redefinition failed: attempted to change the schema (add/remove fields)";
                break;

        case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "class redefinition failed: attempted to change superclass or interfaces";
                break;

        case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "class redefinition failed: attempted to delete a method";
                break;

        case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "class redefinition failed: attempted to change the class modifiers";
                break;

        case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "class redefinition failed: attempted to change method modifiers";
                break;

        case JVMTI_ERROR_UNSUPPORTED_VERSION:
                throwableClassName = "java/lang/UnsupportedClassVersionError";
                break;

        case JVMTI_ERROR_NAMES_DONT_MATCH:
                throwableClassName = "java/lang/NoClassDefFoundError";
                message = "class names don't match";
                break;

        case JVMTI_ERROR_INVALID_CLASS_FORMAT:
                throwableClassName = "java/lang/ClassFormatError";
                break;

        case JVMTI_ERROR_UNMODIFIABLE_CLASS:
                throwableClassName = "java/lang/instrument/UnmodifiableClassException";
                break;

        case JVMTI_ERROR_INVALID_CLASS:
                throwableClassName = "java/lang/InternalError";
                message = "class redefinition failed: invalid class";
                break;

        case JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED:
                throwableClassName = "java/lang/UnsupportedOperationException";
                message = "unsupported operation";
                break;

        case JVMTI_ERROR_INTERNAL:
        default:
                throwableClassName = "java/lang/InternalError";
                break;
        }

    if ( message != NULL ) {
        jboolean errorOutstanding;

        messageString = (*jnienv)->NewStringUTF(jnienv, message);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert_msg(!errorOutstanding, "can't create exception java string");
    }
    return createThrowable( jnienv,
                            throwableClassName,
                            messageString);

}


/**
 *  Calls toString() on the given message which is the same call made by
 *  Exception when passed a throwable to its constructor
 */
jstring
getMessageFromThrowable(    JNIEnv*     jnienv,
                            jthrowable  exception) {
    jclass      exceptionClass      = NULL;
    jmethodID   method              = NULL;
    jstring     message             = NULL;
    jboolean    errorOutstanding    = JNI_FALSE;

    jplis_assert(isSafeForJNICalls(jnienv));

    /* call getMessage on exception */
    exceptionClass = (*jnienv)->GetObjectClass(jnienv, exception);
    errorOutstanding = checkForAndClearThrowable(jnienv);
    jplis_assert(!errorOutstanding);

    if (!errorOutstanding) {
        method = (*jnienv)->GetMethodID(jnienv,
                                        exceptionClass,
                                        "toString",
                                        "()Ljava/lang/String;");
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert(!errorOutstanding);
    }

    if (!errorOutstanding) {
        message = (*jnienv)->CallObjectMethod(jnienv, exception, method);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert(!errorOutstanding);
    }

    jplis_assert(isSafeForJNICalls(jnienv));

    return message;
}


/**
 *  Returns whether the exception given is an unchecked exception:
 *  a subclass of Error or RuntimeException
 */
jboolean
isUnchecked(    JNIEnv*     jnienv,
                jthrowable  exception) {
    jboolean result = JNI_FALSE;

    jplis_assert(isSafeForJNICalls(jnienv));
    result =    (exception == NULL) ||
                isInstanceofClassName(jnienv, exception, "java/lang/Error") ||
                isInstanceofClassName(jnienv, exception, "java/lang/RuntimeException");
    jplis_assert(isSafeForJNICalls(jnienv));
    return result;
}

/*
 *  Returns the current throwable, if any. Clears the throwable state.
 *  Clients can use this to preserve the current throwable state on the stack.
 */
jthrowable
preserveThrowable(JNIEnv * jnienv) {
    jthrowable result = (*jnienv)->ExceptionOccurred(jnienv);
    if ( result != NULL ) {
        (*jnienv)->ExceptionClear(jnienv);
    }
    return result;
}

/*
 *  Installs the supplied throwable into the JNIEnv if the throwable is not null.
 *  Clients can use this to preserve the current throwable state on the stack.
 */
void
restoreThrowable(   JNIEnv *    jnienv,
                    jthrowable  preservedException) {
    throwThrowable( jnienv,
                    preservedException);
    return;
}

void
throwThrowable(     JNIEnv *    jnienv,
                    jthrowable  exception) {
    if ( exception != NULL ) {
        jint result = (*jnienv)->Throw(jnienv, exception);
        jplis_assert_msg(result == JNI_OK, "throwThrowable failed to re-throw");
    }
    return;
}


/*
 *  Always clears the JNIEnv throwable state. Returns true if an exception was present
 *  before the clearing operation.
 */
jboolean
checkForAndClearThrowable(  JNIEnv *    jnienv) {
    jboolean result = (*jnienv)->ExceptionCheck(jnienv);
    if ( result ) {
        (*jnienv)->ExceptionClear(jnienv);
    }
    return result;
}

/* creates a java.lang.InternalError and installs it into the JNIEnv */
void
createAndThrowInternalError(JNIEnv * jnienv) {
    jthrowable internalError = createInternalError( jnienv, NULL);
    throwThrowable(jnienv, forceFallback(internalError));
}

void
createAndThrowThrowableFromJVMTIErrorCode(JNIEnv * jnienv, jvmtiError errorCode) {
    jthrowable throwable = createThrowableFromJVMTIErrorCode(jnienv, errorCode);
    throwThrowable(jnienv, forceFallback(throwable));
}

void
mapThrownThrowableIfNecessary(  JNIEnv *                jnienv,
                                CheckedExceptionMapper  mapper) {
    jthrowable  originalThrowable   = NULL;
    jthrowable  resultThrowable     = NULL;

    originalThrowable = preserveThrowable(jnienv);

    /* the throwable is now cleared, so JNI calls are safe */
    if ( originalThrowable != NULL ) {
        /* if there is an exception: we can just throw it if it is unchecked. If checked,
         * we need to map it (mapper is conditional, will vary by usage, hence the callback)
         */
        if ( isUnchecked(jnienv, originalThrowable) ) {
            resultThrowable = originalThrowable;
        }
        else {
            resultThrowable = (*mapper) (jnienv, originalThrowable);
        }
    }

    /* re-establish the correct throwable */
    if ( resultThrowable != NULL ) {
        throwThrowable(jnienv, forceFallback(resultThrowable));
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java JavaExceptions.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.