¿Cómo puedo clonar una excepción en Java?

I have a data updater thread that uses callbacks to return either result or an exception to a manager. I use semaphore to synchronize manager start and getting the results of a background thread's work (either result or a an exception). Manager is launched only by other threads by calling runUpdate que los usos synchronizer.tryAcquire(). Other threads can try to get result from a manager at any time. So when that happens I check if background thread finished it's work by checking semaphore state. So to return a result I clone it by a constructor and than I release semaphore. But in a case of exception I cannot do this. I must either create a new Exception thus losing it's actual class and stack trace or release semaphore before throwing an exception and risk getting incorrect results (getReturnedException() can already return null or other exception).

private final Semaphore synchronizer = new Semaphore(1, true);

public List<Map<String, Object>> getResult() throws Exception {
    if (synchronizer.tryAcquire(1, TimeUnit.MILLISECONDS)) {
        if (getReturnedException() == null) {
            List<Map<String, Object>> tempResult = new ArrayList<>(result);
            synchronizer.release();
            return tempResult;
        } else {
            Exception clonedEx = cloneException(getReturnedException()); //some way to clone an exception
            throw clonedEx;
        }
    } else {
        throw new Exception("Background thread is still working");
    }
}

public void processException(Exception ex, Thread thread) {
    setReturnedException(ex);
    synchronizer.release();
}

So is there a way to implement cloneException ¿función?

preguntado el 27 de noviembre de 13 a las 06:11

You can throw it without cloning :) Also, your getReturnedException is null in the else branch. Are you sure? -

Yeah, I made a mistake. Edited the post. -

2 Respuestas

You might be able to accomplish this without any cloning, as well as solve another problem, which is that you're currently not releasing synchronizer si tiras clonedEx. Prueba esto en su lugar:

Exception ex = getReturnedException();
try {
    if (ex == null) {  //Did you mean equals null here?
        List<Map<String, Object>> tempResult = new ArrayList<>(result);        
        return tempResult;
    } else {
        throw ex;
    }
} finally {
    synchronizer.release();
}

respondido 27 nov., 13:06

Yes I meant ex == null. Edited the post. I do know how this construction works (try { return false; } finally { return true; } will return true). But I'm not sure if this is the same when throwing an exception. - DeGriz

Per the official Java docs: "The finally block siempre executes when the try block exits". So the answer is yes, the finally is called whether an exception is thrown or your normal return statement occurs. - codificador_musical

@musical_coder: Always, except when try/catch has a System.exit call or something really bad happens(Example : JVM error) - Silviu Burcea

Seeing as your whole program is dead at that point, there ain't much you can do :) This approach I coded here prepares you for just about every "handleable" situation. - codificador_musical

You don't need to clone the exception. You just need to release your resource in a finally block, so that it always happens.

respondido 27 nov., 13:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.