应该在JNI接口中抛出泛型异常还是专用异常? 脚本 java代码库使用C++库。实现JNI接口是为了让API使用Java调用访问本机方法
到目前为止,实现这一点的方法是在Java端使用函数:应该在JNI接口中抛出泛型异常还是专用异常? 脚本 java代码库使用C++库。实现JNI接口是为了让API使用Java调用访问本机方法,java,c++,exception,java-native-interface,Java,C++,Exception,Java Native Interface,到目前为止,实现这一点的方法是在Java端使用函数: private static native void useFancyNativeFunction() throws SomeCustomException; JNI头文件中相应的方法包括错误处理,在需要时会抛出Java异常: try { // do amazing C++ things } catch ( const std::runtime_error& e ) { jclass Exception = env-
private static native void useFancyNativeFunction() throws SomeCustomException;
JNI头文件中相应的方法包括错误处理,在需要时会抛出Java异常:
try
{
// do amazing C++ things
}
catch ( const std::runtime_error& e )
{
jclass Exception = env->FindClass( "util/somestuff/SomeCustomException" );
env->ThrowNew( Exception, e.what() );
}
这意味着,如果在本机代码的特定块中引发运行时异常,则会在JVM封装的应用程序中引发和处理自定义Java异常
问题:
这引发了一场有趣的讨论,但尚未解决:
在此上下文中引发自定义异常意味着我们在JNI接口实现和特定Java代码库之间创建依赖关系。另一种方法是本机抛出泛型Java异常,然后通过Java代码捕获它们,然后抛出专用异常 因此,在给定的场景中,有两种选择:
- 在我们的例子中,对于两个版本都没有缺点,因为只有一个java代码库和一个C++代码库。JNI接口不需要重用
- 依赖项只存在于接口本身中,而不存在于库中。后者正在被我们重用,但是没有涉及Java
- 这两种选择都不太可能对我们产生重大影响。我只是出于兴趣而问
- 使用Java标准异常,如
。我们可以相信它将永远存在,这样依赖性就不会产生任何问题RuntimeException
- 使用您自己的异常类型,如
。我建议不要这样命名。这并不是描述故障原因,而是描述故障的位置。您必须确保异常类在Java包装器库中可用MyWonderfullLibraryException
- 使用自己的异常类型,如
。从技术上讲,这与 在前面的选择中,IMHO更好地将失败原因描述为Java计算模型中无法适当描述的原因NativeCppException
- 在不创建Java异常的情况下,从本机代码通信故障,例如通过特殊故障返回值。这可能比您当前的方法更容易(而且性能更高,创建的代码依赖性更少)
在您的情况下,原因隐藏在文本中的某个地方,该代码来自C++ <代码> RunTimeOrthEngult。您可能会尝试将其映射到不同的适当Java异常类型,但“您不需要它(YAGNI)”
<>我首选的选择是“代码> NATEVECPPExpAc/Cuth>,总结C++世界中可能发生的一切。有些来电者可能有足够的勇气捕捉到这样的异常,可能只有在他有一个非本地的替代品可用的情况下 (脚注1) 我知道对于个别异常类型的重要性有不同的观点,但我还没有找到一个令人信服的论据来证明在野外经常看到的异常类型层次结构极其复杂 创建异常类型是为了供代码的某些部分使用,否则这是典型的YAGNI情况 关于内部调用的失败,方法通常分为三类:- 绝大多数方法都属于第一类(或者应该属于第一类,不是设计过度了吗)
- 对于一些方法,开发人员创建了回退策略。大多数情况下,不仅针对特定的失败,而且针对任何失败,尝试这种策略都是无害的
- 在极少数情况下,故障原因对selec很重要
// Java caller try { useFancyNativeFunction(); } catch( SomeCustomException e ) { // treat custom exception directly here } // Java native call private static native void useFancyNativeFunction() throws SomeCustomException; // C++ JNI header try { // do amazing C++ things } catch ( const std::runtime_error& e ) { jclass Exception = env->FindClass( "util/somestuff/SomeCustomException" ); env->ThrowNew( Exception, e.what() ); }
// Java caller try { useFancyNativeFunction(); } catch( RuntimeException e ) { // catch generic, throw specialized, handle elsewhere throw new SomeCustomException( e.getMessage() ); } // Java native call private static native void useFancyNativeFunction() throws RuntimeException; // C++ JNI header try { // do amazing C++ things } catch ( const std::runtime_error& e ) { jclass Exception = env->FindClass( "java/lang/RuntimeException" ); env->ThrowNew( Exception, e.what() ); }