Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JNI是否保留errno?_Java_Java Native Interface - Fatal编程技术网

Java JNI是否保留errno?

Java JNI是否保留errno?,java,java-native-interface,Java,Java Native Interface,我正在编写一些JNI代码来包装一些C函数。其中一些C函数seterrno出现错误。如果我能将异常处理从JNI代码移到Java代码,我的代码会更简单。我的计划是,在出现错误时,必须返回JNI函数null,然后在Java代码查询errno中构造并抛出异常。为了让这一切顺利进行,JNI必须让errno保持原样。如果我是你,我会尽快带着例外离开 #include <stdio.h> #include <stdlib.h> #include <string.h> #in

我正在编写一些JNI代码来包装一些C函数。其中一些C函数set
errno
出现错误。如果我能将异常处理从JNI代码移到Java代码,我的代码会更简单。我的计划是,在出现错误时,必须返回JNI函数
null
,然后在Java代码查询
errno
中构造并抛出异常。为了让这一切顺利进行,JNI必须让
errno
保持原样。

如果我是你,我会尽快带着例外离开

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include "recipeNo019_ThrowException.h"

JNIEXPORT void JNICALL Java_recipeNo019_ThrowException_throwException
  (JNIEnv * env, jobject obj) {

  char exceptionBuffer[1024];

  if(fopen("/this_will_fail", "r") == NULL) {

    sprintf (exceptionBuffer, "%d:%s", errno, strerror(errno));
    (*env)->ThrowNew (env,
                    (*env)->FindClass (env, "java/lang/Exception"),
                    exceptionBuffer);
  }

}

更新 请注意,随着
JNI
的参与,事情可能会变得复杂(尤其是共享数据-
errno

您可以想象其中一个场景-如下所示:

public static class ErrnoGenerator implements Runnable {

  boolean shouldIFail = false;
  ThrowException exceptionGenerator = null;

  public ErrnoGenerator(
             ThrowException exceptionGenerator, 
             boolean shouldIFail) {
    this.exceptionGenerator = exceptionGenerator;
    this.shouldIFail = shouldIFail;
  }

  public void run() {
    try {
      if(shouldIFail) {
        exceptionGenerator.throwException( shouldIFail );
        Thread.sleep(1000);
        System.out.println(
            "true:    expected == 2: " 
          + exceptionGenerator.getErrno());
      } else {
        Thread.sleep(500);
        exceptionGenerator.throwException( shouldIFail );
        System.out.println(
            "false: no expectations: " 
          + exceptionGenerator.getErrno());
      }
    } catch (InterruptedException e) {
    }
  }
}

public static void main(String[] args) {
  ThrowException thx = new ThrowException();

  Thread t1 = new Thread(new ErrnoGenerator(thx, true));
  Thread t2 = new Thread(new ErrnoGenerator(thx, false));
  t1.start();
  t2.start();
  while(t1.isAlive() || t2.isAlive());
}
然而,即使没有基于
Java
的线程调用
JNI
,您也可以进入竞争条件

// This will set errno to "2"
thx.throwException( true );
try {
  Path file = Paths.get("/tmp/path-to-file");
  byte[] buf = "hello".getBytes();
  Files.write(file, buf);
} catch(Exception ex) {
}

// it's gone - errno contains something completely
// different to what you have expected to be found
System.out.println(
    "true:    expected == 2: " 
  + thx.getErrno());

如果我是你,我会尽快带着例外离开

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include "recipeNo019_ThrowException.h"

JNIEXPORT void JNICALL Java_recipeNo019_ThrowException_throwException
  (JNIEnv * env, jobject obj) {

  char exceptionBuffer[1024];

  if(fopen("/this_will_fail", "r") == NULL) {

    sprintf (exceptionBuffer, "%d:%s", errno, strerror(errno));
    (*env)->ThrowNew (env,
                    (*env)->FindClass (env, "java/lang/Exception"),
                    exceptionBuffer);
  }

}

更新 请注意,随着
JNI
的参与,事情可能会变得复杂(尤其是共享数据-
errno

您可以想象其中一个场景-如下所示:

public static class ErrnoGenerator implements Runnable {

  boolean shouldIFail = false;
  ThrowException exceptionGenerator = null;

  public ErrnoGenerator(
             ThrowException exceptionGenerator, 
             boolean shouldIFail) {
    this.exceptionGenerator = exceptionGenerator;
    this.shouldIFail = shouldIFail;
  }

  public void run() {
    try {
      if(shouldIFail) {
        exceptionGenerator.throwException( shouldIFail );
        Thread.sleep(1000);
        System.out.println(
            "true:    expected == 2: " 
          + exceptionGenerator.getErrno());
      } else {
        Thread.sleep(500);
        exceptionGenerator.throwException( shouldIFail );
        System.out.println(
            "false: no expectations: " 
          + exceptionGenerator.getErrno());
      }
    } catch (InterruptedException e) {
    }
  }
}

public static void main(String[] args) {
  ThrowException thx = new ThrowException();

  Thread t1 = new Thread(new ErrnoGenerator(thx, true));
  Thread t2 = new Thread(new ErrnoGenerator(thx, false));
  t1.start();
  t2.start();
  while(t1.isAlive() || t2.isAlive());
}
然而,即使没有基于
Java
的线程调用
JNI
,您也可以进入竞争条件

// This will set errno to "2"
thx.throwException( true );
try {
  Path file = Paths.get("/tmp/path-to-file");
  byte[] buf = "hello".getBytes();
  Files.write(file, buf);
} catch(Exception ex) {
}

// it's gone - errno contains something completely
// different to what you have expected to be found
System.out.println(
    "true:    expected == 2: " 
  + thx.getErrno());

我认为最好让JNI代码设置除
errno
之外的内容,并通过JNI公开的接口获取该错误值。
errno
的问题在于它可以被许多操作所触及。最好是使用自己的错误值来指示错误,而不是依赖于
errno
标准值。这样,您就可以报告
errno
值范围内未涵盖的错误,并提供更好、更具信息性的诊断。请参阅中的讨论,可能无法保证
errno
不会更改。所有代码所要做的就是调用一个函数,而C标准中的文档没有提到
errno
:无论是否存在错误,只要在本国际标准的函数描述中未记录errno的使用,则可通过库函数调用将errno的值设置为非零我认为最好让JNI代码设置除
errno
之外的内容,并通过JNI公开的接口获取该错误值。
errno
的问题在于它可以被许多操作所触及。最好是使用自己的错误值来指示错误,而不是依赖于
errno
标准值。这样,您就可以报告
errno
值范围内未涵盖的错误,并提供更好、更具信息性的诊断。请参阅中的讨论,可能无法保证
errno
不会更改。所有代码所要做的就是调用一个函数,而C标准中的文档没有提到
errno
:“无论是否存在错误,只要在本国际标准的函数描述中未记录errno的使用,则可以通过库函数调用将errno的值设置为非零。”是的,这似乎是最好的做法。不幸的是,
FindClass
ThrowNew
也会失败。@PhilippeMarschall如果
FindClass“java/lang/Exception”)
ThrowNew
失败,除了调用
中止()
,你就无能为力了。这可能是最好的方法,取决于你的需求。\n是的,这似乎是最好的办法。不幸的是
FindClass
ThrowNew
也可能失败。@PhilippeMarschall如果
FindClass“java/lang/Exception”)
ThrowNew
失败,那么除了调用
中止()
,您就无能为力了。根据您的需求,这可能是最好的方法\