Determining whether STDERR is going to terminal - java

I have a suite of Java programs which are used as command-line tools on our Linux servers. Most of them use a class that prints a progress bar on STDERR, similar to Perl's Term::ProgressBar.
I'd like to have the progress bar shown whenever STDERR is going to the terminal and automatically disable itself when STDERR is redirected so that there aren't all sorts of progress bar pieces in the redirected data.
Checking System.console() == null was my first thought, but redirecting STDOUT is enough to make this true, even if STDERR is still going to the terminal. Is there anything I can check that is specific to STDERR? A solution that is Linux-specific or that uses native APIs would be ok for my needs.

I think what you're looking for is isatty(3), in unistd.h. There's no way to tell whether a file handle has been redirected, period, but that'll tell you whether it's still interactive. See the source for the tty command in GNU coreutils.

After combining #chrylis's pointer with this answer and doing a little tweaking, what I finally ended up with is:
create and compile Java class with native method signature
use javah to generate C header file
create .cpp file, implementing function with isatty
compile C++ code into shared library
run Java program, using -Djava.library.path=... to tell it where your custom library is
Java class:
package com.example.cli;
class LinuxTerminalSupport {
public native boolean isStderrVisible();
static {
System.loadLibrary("term");
}
}
ant target to generate .h:
<target name="generate-native-headers">
<javah destdir="native/" verbose="yes">
<classpath refid="compile.class.path"/>
<class name="com.example.cli.LinuxTerminalSupport" />
</javah>
</target>
.cpp file:
#include "com_example_cli_LinuxTerminalSupport.h"
#include "unistd.h"
using namespace std;
JNIEXPORT jboolean JNICALL Java_com_example_cli_LinuxTerminalSupport_isStderrVisible(JNIEnv * env, jobject obj) {
return isatty(fileno(stderr)) == 1;
}
Makefile (change java includes to reflect your $JAVA_HOME):
linux: LinuxTerminalSupport.o
g++ -I/usr/java/jdk1.6.0_13/include -I/usr/java/jdk1.6.0_13/include/linux \
-o libterm.so -shared -Wl,-soname,term.so LinuxTerminalSupport.o -lc
LinuxTerminalSupport.o: LinuxTerminalSupport.cpp
g++ -c -I/usr/java/jdk1.6.0_13/include -I/usr/java/jdk1.6.0_13/include/linux LinuxTerminalSupport.cpp

Related

How to fix Java 15 JNI "UnsatisfiedLinkError: A dynamic link library (DLL) initialization routine failed"

I have found other posts of people having this exact error, but not one thus far has had a solution that worked for me. For reference, here are the things I have found:
https://community.oracle.com/tech/developers/discussion/2233828/jni-link-error-a-dynamic-link-library-dll-initialization-routine-failed
JNI UnsatisfiedLinkError: A dynamic link library (DLL) initialization routine failed
https://www.debugcn.com/en/article/5175409.html
https://coderanch.com/t/132356/engineering/java-lang-UnsatisfiedLinkError
Either their solution was not relevant to my particular scenario, or it did not fix the issue for me.
Everything is being compiled on the command line with a Windows 10 computer and using GCC (gcc-5.1.0-tdm64-1-c++) for compiling the C++ portions into a .dll, and JDK 15.0.1's javac tool. There are three relevant files here, one being the header file derived from the java file.
Main.java:
public class Main {
static {
System.load("C:\\Users\\17659\\Documents\\Programming\\C++ & Java - JNI Tests\\library.dll");
//System.loadLibrary("library");
}
public static void main(String[] args) {
new Main().outputText();
}
private native void outputText();
}
Main.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Main */
#ifndef _Included_Main
#define _Included_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Main
* Method: outputText
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Main_outputText
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Library.cpp:
#include <iostream>
#include "Main.h"
JNIEXPORT void JNICALL Java_Main_outputText(JNIEnv * a, jobject b)
{
std::cout << "testing";
}
They are contained all within the folder with the absolute path of C:\Users\17659\Documents\Programming\C++ & Java - JNI Tests. With a command prompt set to that as the current directory, I run the following commands in order:
g++ -c -o Library.o -I"C:\Users\17659\Documents\jdk-15.0.1\include" -I"C:\Users\17659\Documents\jdk-15.0.1\include\win32" Library.cpp
g++ -shared -o library.dll Library.o
javac Main.java
java Main
Despite the multiple things I have tried, I always get this same error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\17659\Documents\Programming\C++ & Java - JNI Tests\library.dll: A dynamic link library (DLL) initialization routine failed
at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:383)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:227)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:169)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2407)
at java.base/java.lang.Runtime.load0(Runtime.java:747)
at java.base/java.lang.System.load(System.java:1857)
at Main.<clinit>(Main.java:3)
I have used nm on the resulting .dll to make sure the name of the function is correct, and it does seem to be exactly as it should.
The entire point of this little project of mine is to figure out how JNI works, since I have a plan to write a small portion of a program in C++. The rest of the program though would work best in Java (for me). I do not know what I need to do to get this program to work, I have spent approximately 2 hours of googling and fiddling attempting to get it to function. This is on a 64-bit OS. How can I make this program run and print out the very little amount of text I would like it to print out?
Update: As per #JornVernee removing the line #include <iostream> and replacing the std::cout with a printf() to write to the console did actually work. So my question now becomes this: why does including a standard C++ header cause an error?
Well, #JornVernee effectively nailed the issue right on the head. It was a mismatch between the standard library I had for C++ and the one being loaded. I changed the version of GCC I was using to a more up-to-date version, recompiled the entire project, and the program works now.

Write & call Swift code using Java’s JNI

As you see here one can perform native C/C++ method calls from Java code, thanks to JVM’s JNI. But how about performing calls of Swift methods? Is this possible or going to be possible (can be implemented in a reasonable time frame) as Swift becomes more popular?
I want to access Apple’s native API that is only accessible when one writes apps in either Objective-C or Swift. As the JVM is just being ported to ARMv8 (64-bit), I could also imagine the JVM as an alternative runtime for iOS apps in the future. But this might be the future... The present is: The JVM runs on Mac OS X and one can write apps for Mac OS X in Swift that can access some APIs that might be not accessible to Java apps in the same way.
Well, roughly 5½ years later, it turned out, it wasn't the future... No JVMs on iOS.
But you can definitely do it, i.e., call Swift APIs from Java. That said, it's quite cumbersome, because AFAIK, you have to take a detour via C/C++.
Here's the deal:
As you know, you can use JNI to call C code.
From C you can call Swift.
The following relies heavily on this question.
Code
Your Java code is in helloworld/SwiftHelloWorld.java:
package helloworld;
public class SwiftHelloWorld {
static {
System.loadLibrary("SwiftHelloWorld");
}
public static native void printHelloWorldImpl();
public static void main(final String[] args) {
printHelloWorldImpl();
}
}
Now write the native C code (file helloworld_SwiftHelloWorld.c):
#include <jni.h>
#include <stdio.h>
#include "helloworld_SwiftHelloWorld.h"
#include "helloworld_SwiftHelloWorld_swift.h"
JNIEXPORT void JNICALL Java_helloworld_SwiftHelloWorld_printHelloWorldImpl
(JNIEnv *env, jclass clazz) {
int result = swiftHelloWorld(42);
printf("%s%i%s", "Hello World from JNI! ", result, "\n");
}
Which uses a header file named helloworld_SwiftHelloWorld_swift.h for our (yet to be written) Swift code:
int swiftHelloWorld(int);
Finally, our Swift code resides in SwiftCode.swift:
import Foundation
// force the function to have a name callable by the c code
#_silgen_name("swiftHelloWorld")
public func swiftHelloWorld(number: Int) -> Int {
print("Hello world from Swift: \(number)")
return 69
}
Building
To build all this, we first have to compile the Swift code to a dynamic library:
swiftc SwiftCode.swift -emit-library -o libSwiftCode.dylib -Xlinker -install_name -Xlinker libSwiftCode.dylib
We use the -Xlinker directives to ensure that the dylib's location is relative.
Before we can create the C dylib, we first have to generate the Java headers:
javac -h . helloworld/SwiftHelloWorld.java
Now that we have the Java headers and the Swift dylib, we can compile the C dylib, which links against the Swift dylib:
gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libSwiftHelloWorld.dylib -dynamiclib helloworld_SwiftHelloWorld.c libSwiftCode.dylib
Now that everything is in place, we must make sure that both dylibs are in the same directory and that that directory can be found by Java, i.e., you may need to set -Djava.library.path=<dir of your dylibs>.
Et voilà!
Swift called from Java!

Calling Haskell from Java with C in between

This probably sounds like a nightmare, but I'd really like to get this working. I am using this example for the most part: Calling C from Haskell and am trying to get this working on ubuntu.
I am running this in java:
package test;
public class JniTest {
public native int fib(int x);
}
this in c after creating the .h file with javah: (test_JniTest.c)
#include "test_JniTest.h"
#include "Safe_stub.h"
JNIEXPORT jint JNICALL Java_test_JniTest_fib(JNIEnv * e, jobject o, jint f)
{
return fibonacci_hs(f);
}
and then for reference in haskell (before stub): (Safe.hs)
module Safe where
import Foreign.C.Types
fibonacci :: Int -> Int
fibonacci n = fibs !! n
where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral
foreign export ccall fibonacci_hs :: CInt -> CInt
and this is what i'm trying to compile it with:
ghc -c -O Safe.hs
followed by:
ghc -shared -o libTest.jnilib -optc-O test_JniTest.c
-I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux
and I am getting this error:
/usr/bin/ld: test_JniTest.o: relocation R_X86_64_PC32 against
undefined symbol `fibonacci_hs' can not be used when making a shared
object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status
I am not a c expert by any means and have no idea what to do about this. I tried compiling various ways with -fPIC, but I kept on getting the same error. Any idea what I might be doing wrong?
Thanks!
Although I've pretty much answered this question here: Communication between Java and Haskell, since this issue is more about the error itself, I will be adding the details for that here. The issue stems from Haskell not supporting shared libraries very well, while Java requires them.
Buildings plugins as Haskell shared libs gives us this insight and workaround:
In principle you can use -shared without -dynamic in the link step. That would mean to statically link the rts all the base libraries into your new shared library. This would make a very big, but standalone shared library. However that would require all the static libraries to have been built with -fPIC so that the code is suitable to include into a shared library and we don't do that at the moment.
If we use ldd again to look at the libfoo.so that we've made we will notice that it is missing a dependency on the rts library. This is problem that we've yet to sort out, so for the moment we can just add the dependency ourselves:
$ ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so \
-lHSrts-ghc6.11 -optl-Wl,-rpath,/opt/ghc/lib/ghc-6.11/
This is a workaround because it requires us to know the version of the rts library at build time.
If your goal is to actually get something done (as opposed to just playing around with JNI) I suggest tackling this as a garden variety RPC problem and utilizing one of the many framework/protocols for it:
Protocol Buffers from Google
Thrift from Facebook
Avro (well this is mostly a wire protocol)
From what you are trying to do, Thrift might be your best bet since it describes a full client/server RPC stack but I'm pretty sure any of them would pretty much work over a simple socket.

JNI error while calling a C subroutine

I want to call a C subroutine from Java. I'm using JNI. I have created the .java, .c, and .h files, and compiled a DLL. All the files are in the same folder. But when I run the program, it shows an unsatisfiedlinkError. Where am I going wrong...?
As I am learning JNI, the source code I used is the one from: http://www.ibm.com/developerworks/java/tutorials/j-jni/section2.html and things I have already tried:
Create a dll using Code::Blocks(ide) and GCC as the compiler
Create dll using GCC from command line (Ref. http://sig9.com/node/35 )
I am using Win7 32 bit, and I guess all the methods above generate 32-bit DLLs
All the solutions I found for creating a DLL (shared library) are for MS VC/VCPP and I don't have that on my machine right now.
Where is the problem? DLL files are being generated without any exception, but when I run the Java code, it throws the exception.
PS: If there is any theoretical examples that explains how JNI works and what actually it does, then kindly share the link...
The message or exception being thrown:
c:\myjava1>java Sample1
Exception in thread "main" java.lang.UnsatisfiedLinkError: Sample1.intMethod(I)I
at Sample1.intMethod(Native Method)
at Sample1.main(Sample1.java:11)
At the end of the day after creating dll file lots of times,I am pretty sure that there is possibly no issue with it ,something is wrong with the path ...I have changed the loadlibrary method with load method ,but still no luck,.....
as suggested by a MOD:
I have been discussing about this question on the post:JNI error while calling a C subroutine ,I am posting all the codes here as the comments have limited characters... Sample1.c
#include "jni.h"
#include"Sample_Sample1.h"
JNIEXPORT jint JNICALL Java_Sample_Sample1_test(JNIEnv *env, jobject obj){
return(1);
}
void main(){}
Sample1.java
package Sample;
public class Sample1
{
public native int test();
static{
System.loadLibrary("Sample1");
}
public static void main(String[] args)
{
Sample1 sample = new Sample1();
System.out.println(sample.test());
}
}
Sample_Sample1.h(generated using javah -jni command)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class Sample_Sample1 */
#ifndef _Included_Sample_Sample1
#define _Included_Sample_Sample1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Sample_Sample1
* Method: test
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_Sample_Sample1_test
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Can anyone guide me where the issue is?In earlier post I mentioned that the code I am using is the one from tutorials ,but to simplyfy the things I have changed the codes ...While using **java Sample.Sample1" i am getting:
c:\myjava1>java Sample.Sample1
Exception in thread "main" java.lang.UnsatisfiedLinkError: Sample.Sample1.test()I
at Sample.Sample1.test(Native Method)
at Sample.Sample1.main(Sample1.java:12)
You need to have your library explicitly set on your path.
It may be the case that the flags you are using there aren't quite right. Try this:
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at \
-I[Java_HOME]/include -I[Java_HOME]/include/win32 \
-shared -o Sample1.dll Sample1.c
From MinGW GCC site.
Have you checked your DLL by calling it from a stub C++ application? Pay particular attention to the exact name (including capitalisation) of the method(s) you are calling.
The Javadoc for UnsatisfiedLinkError says "Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native." That probably means either that the name is misspelled or your DLL is not where the JVM is expecting to find it.
Finally solved the problem using System.load() method, System.loadLibrary() Still doesn't work for me...it keeps on giving the same exception, And the I think the issue was with the .dll Thanks to all of you who supported and responded...
After spending 2hrs and analysing the code. Problem is with .dll/.so compilation. Below command works for me:
g++ -dynamiclib HelloJni.cpp -I /usr/include/ -I /usr/lib/jvm/java-1.8.0-openjdk-amd64/include/ -I /usr/lib/jvm/java-1.8.0-openjdk-amd64/include/linux/ -shared -o libHelloJni.so
or
g++ -dynamiclib HelloJni.cpp -I /usr/include/ -I $JAVA_HOME/include/ -I $JAVA_HOME/include/linux/ -shared -o libHelloJni.so
Above command is for linux. In case of Windows, change
[Java_HOME]/include/linux/ ---> [Java_HOME]/include/win/
Mac:
$Java_HOME/include/linux/ ---> $Java_HOME/include/darwin/

How do I find my PID in Java or JRuby on Linux?

I need to find the PID of the current running process on a Linux platform (it can be a system dependent solution). Java does not support getting the process ID, and JRuby currently has a bug with the Ruby method, Process.pid.
Is there another way to obtain the PID?
If you have procfs installed, you can find the process id via the /proc/self symlink, which points to a directory whose name is the pid (there are also files here with other pertinent information, including the PID, but the directory is all you need in this case).
Thus, with Java, you can do:
String pid = new File("/proc/self").getCanonicalFile().getName();
In JRuby, you can use the same solution:
pid = java.io.File.new("/proc/self").canonical_file.name
Special thanks to the #stackoverflow channel on free node for helping me solve this! (specifically, Jerub, gregh, and Topdeck)
Only tested in Linux using Sun JVM. Might not work with other JMX implementations.
String pid = ManagementFactory.getRuntimeMXBean().getName().split("#")[0];
You can use the JNI interface to call the POSIX function getpid(). It is quite straight forward. You start with a class for the POSIX functions you need. I call it POSIX.java:
import java.util.*;
class POSIX
{
static { System.loadLibrary ("POSIX"); }
native static int getpid ();
}
Compile it with
$ javac POSIX.java
After that you generate a header file POSIX.h with
$ javah -jni POSIX
The header file contains the C prototype for the function with wraps the getpid function. Now you have to implement the function, which is quite easy. I did it in POSIX.c:
#include "POSIX.h"
#include <sys/types.h>
#include <unistd.h>
JNIEXPORT jint JNICALL Java_POSIX_getpid (JNIEnv *env, jclass cls)
{
return getpid ();
}
Now you can compile it using gcc:
$ gcc -Wall -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include/linux -o libPOSIX.so -shared -Wl,-soname,libPOSIX.so POSIX.c -static -lc
You have to specify the location where your Java is installed. That's all. Now you can use it. Create a simple getpid program:
public class getpid
{
public static void main (String argv[])
{
System.out.println (POSIX.getpid ());
}
}
Compile it with javac getpid.java and run it:
$ java getpid &
[1] 21983
$ 21983
The first pid is written by the shell and the second is written by the Java program after shell prompt has returned. ∎
Spawn a shell process that will read its parent's pid. That must be our pid. Here is the running code, without exception and error handling.
import java.io.*;
import java.util.Scanner;
public class Pid2
{
public static void main(String sArgs[])
throws java.io.IOException, InterruptedException
{
Process p = Runtime.getRuntime().exec(
new String[] { "sh", "-c", "ps h -o ppid $$" });
p.waitFor();
Scanner sc = new Scanner(p.getInputStream());
System.out.println("My pid: " + sc.nextInt());
Thread.sleep(5000);
}
}
This solution seems to be the best if the PID is to be obtained only to issue another shell command. It's enough to wrap the command in back quotes to pass it as an argument to another command, for example:
nice `ps h -o ppid $$`
This may substitue the last string in the array given to exec call.
Java 9 finally offers an official way to do so with ProcessHandle:
ProcessHandle.current().pid();
This:
First gets a ProcessHandle reference for the current process.
In order to access its pid.
No import necessary as ProcessHandle is part of java.lang.
You can try getpid() in JNR-Posix.
It also has a Windows POSIX wrapper that calls getpid() off of libc. No JNI needed.

Categories