10.3 为什么存在sun.misc.Unsafe,如何在现实世界中使用它?| Java Debug 笔记

231 阅读1分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>

提问:为什么存在sun.misc.Unsafe,如何在现实世界中使用它?

前几天,我遇到了sun.misc.Unsafe软件包,并对它的功能感到惊讶。

我想知道是否有充分的理由使用它。在需要使用它的地方可能会发生什么情况?在现实世界中如何使用它?

此外,如果您确实需要它,这是否表示您的设计可能存在问题?

为什么Java甚至包括此类?

回答1:

Unsafe.throwException-允许抛出已检查的异常而无需声明它们。

在处理反射或AOP的某些情况下,这很有用。

假设您为用户定义的接口构建通用代理。用户可以通过在接口中声明异常来指定在特殊情况下实现会抛出哪个异常。这是我知道的唯一方法,可以在接口的动态实现中引发受检查的异常。

import org.junit.Test;
/** need to allow forbidden references! */ import sun.misc.Unsafe;

/**
 * Demonstrate how to throw an undeclared checked exception.
 * This is a hack, because it uses the forbidden Class {@link sun.misc.Unsafe}.
 */
public class ExceptionTest {

    /**
     * A checked exception.
     */
    public static class MyException extends Exception {
        private static final long serialVersionUID = 5960664994726581924L;
    }

    /**
     * Throw the Exception.
     */
    @SuppressWarnings("restriction")
    public static void throwUndeclared() {
        getUnsafe().throwException(new MyException());
    }

    /**
     * Return an instance of {@link sun.misc.Unsafe}.
     * @return THE instance
     */
    @SuppressWarnings("restriction")
    private static Unsafe getUnsafe() {
        try {

            Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
            singleoneInstanceField.setAccessible(true);
            return (Unsafe) singleoneInstanceField.get(null);

        } catch (IllegalArgumentException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (SecurityException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (NoSuchFieldException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (IllegalAccessException e) {
            throw createExceptionForObtainingUnsafe(e);
        }
    }

    private static RuntimeException createExceptionForObtainingUnsafe(final Throwable cause) {
        return new RuntimeException("error while obtaining sun.misc.Unsafe", cause);
    }


    /**
     * scenario: test that an CheckedException {@link MyException} can be thrown
     * from an method that not declare it.
     */
    @Test(expected = MyException.class)
    public void testUnsingUnsaveToThrowCheckedException() {
        throwUndeclared();
    }
}