这是我的第一篇文章,所以请大家理解一下。 我有一些Java代码,我有一些本机代码。 Java的一部分目前不是那么有趣,所以我会跳到c ++部分: //some more trivial includes #include <signal.h> //these are global variables jclass GLOBAL_CLASS; JNIEnv * GLOBAL_ENV; jobject GLOBAL_OBJECT; jmethodID METHOD_ID; void sigproc(int signo) { if (signo == SIGINT) { signal(SIGINT, sigproc); //if Ctrl-c is pressed I want to call a method within my java class //since I can pass only int to […]
我们有一个Java服务器(Linux 64位)的应用程序,它使用本机代码处理的东西。 本地代码也处理所有的multithreading问题,最近使用boost::context进行光纤交换时得到了增强。 我们现在面临的问题是, AttachCurrentThread失败,光纤交换线程。 经过一些长时间的debugging和testing后,我们find了这样的原因:JVM似乎拒绝了不同于指定的栈指针的线程。 我们通过简单地从带有修改的(但是有效的) rsp的pthread连接到JVM来validation这一点,当rsp被修改时rsp失败。 一个可能的解决scheme会引入某种事件处理机制来解耦来自光纤交换线程的callback,但我真的想避免这种情况。 有没有人知道这个解决方法? 是否可以禁用堆栈检查(Oracle Java 1.7.0_40,64位)? 我们可以修改本地pthreads指向正确的堆栈帧(我怀疑我们可以)? (我们不能提前设置堆栈帧)。
在Java eclipse(Linux)上使用JNI,我加载了一个名为first.so的dynamic共享库。 到目前为止,一切顺利。 问题是,首先,也加载一个名为second.so的dynamic库。 运行程序时,我收到许多关于位于second.so的符号的“未定义符号”错误。 似乎使用JNI加载的库不能在运行时加载其他C库,因为我们处于Java环境中。 我的假设是否正确? 我是否需要特殊的编译标记来编译first.so库,或者是否需要特殊的参数来告诉eclipse它将在运行时加载一个.so文件? 提前致谢!
在用于串行通信的multithreadingLinux程序中,是否有可能(以及什么是最好的方法)终止来自另一个线程的阻塞read()调用? 我想尽可能保持一切尽可能的反应,并避免重复轮询使用超时。 这个问题的背景是,我正在尝试使用JNI为Linux创build一个Scala串行通信库。 我试图保持本地方尽可能简单,其中包括一个read()和close()函数。 在Scala方面,一个线程会调用read()并阻塞,直到来自串口的数据可用。 但是,串口可以通过其他方式closures,导致closures()的调用。 现在,为了释放被阻塞的线程,我不知何故需要取消系统读取调用。
当使用Java Attach API ,我只在Linux上遇到以下链接错误(在不同的机器上试过): Exception in thread "main" java.lang.UnsatisfiedLinkError: sun.tools.attach.WindowsAttachProvider.tempPath()Ljava/lang/String; at sun.tools.attach.WindowsAttachProvider.tempPath(Native Method) at sun.tools.attach.WindowsAttachProvider.isTempPathSecure(WindowsAttachProvider.java:74) at sun.tools.attach.WindowsAttachProvider.listVirtualMachines(WindowsAttachProvider.java:58) at com.sun.tools.attach.VirtualMachine.list(VirtualMachine.java:134) at sun.tools.jconsole.LocalVirtualMachine.getAttachableVMs(LocalVirtualMachine.java:151) at sun.tools.jconsole.LocalVirtualMachine.getAllVirtualMachines(LocalVirtualMachine.java:110) … 有趣的是,在Solaris和Windows上,它是开箱即用的。 我尝试了几个指定java.library.path组合指向包含libattach.so的目录,但没有运气。 这里有什么问题? 作为一个奖励问题 : 有没有办法看到哪个本地库实际绑定到一个Java类?
我正在试图find一种方法来确定Java API需要哪些库来工作,特别是BROWSE函数。 我阅读了一些指南,错误报告和解决方法,但都没有工作。 我可以通过安装libgnome2-0和gvfs-backends包来使它在Debian上工作。 第一个是典型的推荐(由解决同样的问题的人),第二个是一个幸运的猜测,因为看起来桌面API需要vfs。 不过,即使安装了这两个软件包,我也无法在Ubuntu 14.04上做这个工作。 所以我的问题是:我怎样才能find哪些库的Java桌面API需要在Linux上? 特别是Ubuntu 14.04上的Oracle JDK 8。 是否有可能以某种方式捕获哪些库是桌面API使用或从本机代码获取一些错误输出? 编辑 :我创build了一个正在尝试使用浏览的代码行: public class Main { public static void main(String[] args) throws URISyntaxException, IOException { Desktop.getDesktop().browse(new URI("http://www.google.com")); } } 我试图运行一个命令来跟踪执行testing期间所请求的所有文件: strace -e open,access -f -o browse java -jar BrowseTester.jar 我得到了很多的输出,指出Java本机和Linux本机库正在寻找,find和访问,但我不知道如何检测到实际上丢失什么。 输出示例: 30171 open("/usr/lib/x86_64-linux-gnu/gvfs/tls/x86_64/libgvfscommon.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) […]
10月25日更新: 现在我知道是什么原因造成了这个问题。 1)subprocess自杀,这就是为什么strace / perf / auditctl无法追踪它。 2)创build进程的JNI调用是从Java线程触发的。 当线程最终死亡时,它也正在破坏它创build的过程。 3)在我的代码fork和execve()一个subprocess,我有代码来监视父进程的死亡和杀死我的subprocess使用以下行:prctl(PR_SET_PDEATHSIG,SIGKILL); 我的错,在b / c之前,我没有特别留意这个标志,它被认为是我的其他项目的最佳实践,其中subprocess从主线程派生出来。 4)如果我注释掉这个问题,问题就没有了。 最初的目的是在父进程结束后终止subprocess。 即使没有这个标志,它仍然是正确的行为。 看起来像Ubuntu的框默认行为。 5)最后发现它是一个内核bug,在内核版本3.4.0中修复,我的AWS的ubuntu盒子是内核版本3.13.0-29-generic。 有几个有用的链接来解决这个问题: a) http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them b) 在父线程退出时调用prctl(PR_SET_PDEATHSIG,SIGNAL),而不是父进程退出 。 c) https://bugzilla.kernel.org/show_bug.cgi?id=43300 10月15日更新: 非常感谢所有的build议。 我正在从系统的一个区域调查到另一个区域。 很难find一个理由。 我想知道2件事情。 1)为什么强大的工具,如strace,auditctl和perf脚本不能追查谁造成了杀害? 2)+++杀死了SIGKILL +++真的意味着它从信号中被杀死了吗? 原来的post 我有一个从Ubuntu 12的Java应用服务器通过JNI接口启动的长时间运行的C进程。 我使用JNI接口来启动一个进程而不是通过Java的进程生成器的原因是性能方面的原因。 java进程生成器做IPC的效率非常低,特别是b / c额外的缓冲引入了很长的延迟。 它会被SIGKILL神秘地终止。 我发现的方式是通过strace,它说:“+++杀死了SIGKILL +++” 我检查了以下内容: 这不是一个崩溃。 这不是一个OOM。 没有在dmesg。 我的进程只使用1G内存的3.3%。 Java层没有杀死进程。 如果代码终止进程,我会在JNI代码中logging一个日志,但是没有写入日志来表明这一点。 这不是一个许可问题。 我试图以sudo或其他用户身份运行,这两种情况都会导致进程被终止。 如果我在shell中本地运行进程,一切工作正常。 更重要的是,在我长时间运行的C代码中,我忽略了信号SIGHUP。 […]
我们有一个java进程作为本地系统用户在Windows上运行,需要访问系统中另一个用户拥有的文件。 从我所了解的本地系统用户应该有权模仿该用户。 为此,我们传递正在访问文件的程序的tid和pid,并从中获取用户信息(令牌)。 然后我们在当前线程上设置标记。 像这样的东西: DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityImpersonation,TokenImpersonation,&hTokenDup); SetThreadToken(NULL, hTokenDup); 其中hToken是通过打开线程,然后通过他们的ID进行处理获得的。 问题是,当我试图访问一个文件,只有用户可以访问,没有其他人我无法读取它。 我得到一个访问被拒绝的错误。 所以问题是我是否应该能够通过模拟访问这个文件,如果是的话,这是正确的冒充另一个用户给予一个threadid和PID。 我想我也会看到Windows 7和Windows XP之间的不同行为。
如何在Windows任务列表中的进程被java杀死的时候得到callback?我怎么监控这个事件? 我想知道,如果进程被杀害,然后开始自动? 万分感谢!
我目前正在使用JNI来调用位于jar文件中的方法的Windows桌面应用程序。 我需要知道打包我的应用程序的最佳方式,以便它可以链接到jvm.dll。 我不确定是否应该将JDK的bin目录中find的所有二进制文件打包到我的安装文件中(不确定是否允许我这样做)? 问题是直接find在JDK安装path中find的jvm.dll在线链接的所有示例。 由于我的应用程序是商业应用程序,因此我不能依赖或要求每个用户都应该将JDK安装在我的应用程序旁边,因为这太荒谬了。 请有人澄清最好的方法来打包这样的应用程序? 问候