DYLD_PRINT_LIBRARIES not working - java

Trying to experiment with other DYLD_ properties I've found that jvm is manipulating with properties and they are ignored during execution.
My Java test:
class Env {
public static void main(String... args) {
System.getenv().entrySet().stream().forEach(e -> System.out.println(e.getKey() + " = " + e.getValue()));
}
}
Invocation:
$ export DYLD_PRINT_LIBRARIES=1
$ export MY_PRINT_LIBRARIES=2
$ javac Env.java && java Env|grep PRINT
MY_PRINT_LIBRARIES = 2
$
On the other side, my C test:
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
while (*envp) {
printf("%s\n", *envp);
envp++;
}
return 0;
}
Invocation:
$ gcc env.c && ./a.out|grep PRINT
dyld: loaded: /Users/okutane/test/java/./a.out
dyld: loaded: /usr/lib/libSystem.B.dylib
dyld: loaded: /usr/lib/system/libcache.dylib
...
dyld: loaded: /usr/lib/libc++.1.dylib
dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib
MY_PRINT_LIBRARIES=2
DYLD_PRINT_LIBRARIES=1
$
I expected jvm test to work too, is there are any workaround?

With the introduction of SIP, all environment variables matching DYLD_* will be stripped before executing a restricted binary. That includes the /usr/bin/java binary you would be using:
$ ls -lOL /usr/bin/java
-rwxr-xr-x 1 root wheel restricted,compressed 58560 Sep 7 06:41 /usr/bin/java*

Related

Changing Java version in Bazel

I am using Bazel as the build tool for my Java project. I have JDK 11 installed on my mac, but Bazel uses Java 8 to build the binaries. Does anyone know how I could change this?
BUILD.bazel
java_binary(
name = 'JavaBinary',
srcs = ['JavaBinary.java'],
main_class = 'JavaBinary',
)
load(
"#bazel_tools//tools/jdk:default_java_toolchain.bzl",
"default_java_toolchain",
)
default_java_toolchain(
name = "default_toolchain",
visibility = ["//visibility:public"],
)
JavaBinary.java
public class JavaBinary {
public static void main(String[] args) {
System.out.println("Successfully executed JavaBinary!");
System.out.println("Version: " + System.getProperty("java.version"));
}
}
WORKSPACE.bazel
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_java",
sha256 = "220b87d8cfabd22d1c6d8e3cdb4249abd4c93dcc152e0667db061fb1b957ee68",
url = "https://github.com/bazelbuild/rules_java/releases/download/0.1.1/rules_java-0.1.1.tar.gz",
)
load("#rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains")
rules_java_dependencies()
rules_java_toolchains()
Run it this way:
bazel run :JavaBinary \
--java_toolchain=:default_toolchain \
--javabase=#bazel_tools//tools/jdk:remote_jdk11
You can also create .bazelrc file an then execute bazel run :JavaBinary:
.bazelrc
build --java_toolchain=:default_toolchain
build --javabase=#bazel_tools//tools/jdk:remote_jdk11

Could not load main class from .java class file

I'm using Python to visualize a graph through a tool named wot using jupyter notebook. It utilizes Gephi, a java-based graph utility. I try to run function to return coordinate output files as below:
run_gephi(input_graph_file, output_coord_file, n_steps):
layout = 'fa'
import psutil
memory = int(0.5 * psutil.virtual_memory()[0] * 1e-9)
classpath = os.path.dirname(
pkg_resources.resource_filename('wot', 'commands/resources/graph_layout/GraphLayout.class')) + ':' + \
pkg_resources.resource_filename('wot', 'commands/resources/graph_layout/gephi-toolkit-0.9.2-all.jar')
subprocess.check_call(['java', '-Djava.awt.headless=true', '-Xmx{memory}g'.format(memory=memory), '-cp', classpath, \
'GraphLayout', input_graph_file, output_coord_file, layout, str(n_steps), str(os.cpu_count())])
Then it returns following error in my jupyter notebook:
CalledProcessError Traceback (most recent call last)
<ipython-input-18-5fc832689b87> in <module>
----> 1 df, adata = compute_force_layout(ds)
<ipython-input-7-6cb84b9e0fa0> in compute_force_layout(ds, n_neighbors, n_comps, neighbors_diff, n_steps)
24 writer.write("{u} {v} {w:.6g}\n".format(u=i + 1, v=j + 1, w=W[i, j]))
25
---> 26 run_gephi(input_graph_file, output_coord_file, n_steps)
27 # replace numbers with cids
28 df = pd.read_table(output_coord_file, header=0, index_col='id')
<ipython-input-16-28772d0d10cc> in run_gephi(input_graph_file, output_coord_file, n_steps)
7 pkg_resources.resource_filename('wot', 'commands/resources/graph_layout/gephi-toolkit-0.9.2-all.jar')
8 subprocess.check_call(['java', '-Djava.awt.headless=true', '-Xmx{memory}g'.format(memory=memory), '-cp', classpath, \
----> 9 'GraphLayout', input_graph_file, output_coord_file, layout, str(n_steps), str(os.cpu_count())])
~/anaconda3/lib/python3.7/subprocess.py in check_call(*popenargs, **kwargs)
339 if cmd is None:
340 cmd = popenargs[0]
--> 341 raise CalledProcessError(retcode, cmd)
342 return 0
343
CalledProcessError: Command '['java', '-Djava.awt.headless=true', '-Xmx25g', '-cp', '/home/iik/.local/lib/python3.7/site-packages/wot/commands/resources/graph_layout:/home/iik/.local/lib/python3.7/site-packages/wot/commands/resources/graph_layout/gephi-toolkit-0.9.2-all.jar', 'GraphLayout', '/tmp/gephiznxedn32.net', '/tmp/coordsd64x05ww.txt', 'fa', '10000', '8']' returned non-zero exit status 1.
and following message was found in terminal
Error: Could not find or load main class GraphLayout
I can found "GraphLayout.java" and "gephi-toolkit-0.9.2-all.jar" files in the path, so I really don't know why it can't be loaded.
Do you have any suggestions?
Add *
The class GraphLayout is not contained in Gephi but defined by GraphLayout.java.

How to create .dylib from existing c project (concorde) for JNI

I am trying to use concorde in a java app
but I can't figure it out.
I have created the java class as follows:
package jconcorde;
public class TSP {
static {
System.loadLibrary("tsp");
}
private native int[] getNNTour(String path);
public static void main(String[] args) {
int [] a = new TSP().getNNTour("st70.tsp");
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
after compiling it using javac -h
I got the following file: jconcorde_TSP.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jconcorde_TSP */
#ifndef _Included_jconcorde_TSP
#define _Included_jconcorde_TSP
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jconcorde_TSP
* Method: getNNTour
* Signature: (Ljava/lang/String;)[I
*/
JNIEXPORT jintArray JNICALL Java_jconcorde_TSP_getNNTour
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
inside of concorde there is a folder named KDTREE i have copied from the kd_main.c some of it into my jconcorde_TSP.c as follows:
#include <jni.h> // JNI header provided by JDK
#include <stdio.h> // C Standard IO Header
#include "jconcorde_TSP.h" // Generated
#include "machdefs.h"
#include "util.h"
#include "kdtree.h"
#include <string.h>
static int norm = CC_EUCLIDEAN;
static int seed = 0;
static char *nodefile2 = (char *) NULL;
JNIEXPORT jintArray JNICALL Java_jconcorde_TSP_getNNTour(JNIEnv *env, jobject thisObj, jstring jstr) {
const char *nodefile = (*env)->GetStringUTFChars(env, jstr, NULL);
strcpy(nodefile2, nodefile);
double val, szeit;
CCdatagroup dat;
int ncount;
int *ttour = (int *) NULL, *tour2 = (int *) NULL;
CCrandstate rstate;
CCutil_init_datagroup (&dat);
seed = (int) CCutil_real_zeit ();
CCutil_sprand (seed, &rstate);
CCutil_gettsplib (nodefile2, &ncount, &dat);
CCutil_dat_getnorm (&dat, &norm);
ttour = CC_SAFE_MALLOC (ncount, int);
szeit = CCutil_zeit ();
if (CCkdtree_nearest_neighbor_tour ((CCkdtree *) NULL, ncount,
CCutil_lprand (&rstate) % ncount, &dat, ttour, &val, &rstate)) {
fprintf (stderr, "Nearest neighbor failed\n");
}
jintArray outJNIArray = (*env)->NewIntArray(env, ncount);
(*env)->SetIntArrayRegion(env, outJNIArray, 0 , ncount, ttour);
return outJNIArray;
}
and the original Makefile of the KDTREE is as follows:
# Generated automatically from Makefile.in by configure.
#
# This file is part of CONCORDE
#
# (c) Copyright 1995--1999 by David Applegate, Robert Bixby,
# Vasek Chvatal, and William Cook
#
# Permission is granted for academic research use. For other uses,
# contact the authors for licensing options.
#
# Use at your own risk. We make no guarantees about the
# correctness or usefulness of this code.
#
SHELL = /bin/sh
SRCROOT = ..
BLDROOT = ..
CCINCDIR=$(SRCROOT)/INCLUDE
srcdir = .
CC = gcc
CFLAGS = -g -O3 -arch x86_64 -I$(BLDROOT)/INCLUDE -I$(CCINCDIR)
LDFLAGS = -g -O3 -arch x86_64
LIBFLAGS = -lm
RANLIB = ranlib
OBJ_SUFFIX = o
o = $(OBJ_SUFFIX)
THISLIB=kdtree.a
LIBSRCS=kdbuild.c kdnear.c kdspan.c kdtwoopt.c
ALLSRCS=kd_main.c $(LIBSRCS)
LIBS=$(BLDROOT)/UTIL/util.a
all: kdtree $(THISLIB)
everything: all kdtree
kdtree: kd_main.$o $(THISLIB) $(LIBS)
$(CC) $(LDFLAGS) -o $# kd_main.$o $(THISLIB) $(LIBS) $(LIBFLAGS)
clean:
-rm -f *.$o $(THISLIB) kdtree
OBJS=$(LIBSRCS:.c=.o)
$(THISLIB): $(OBJS)
$(AR) $(ARFLAGS) $(THISLIB) $(OBJS)
$(RANLIB) $(THISLIB)
.PHONY: $(BLDROOT)/concorde.a
$(BLDROOT)/concorde.a: $(OBJS)
$(AR) $(ARFLAGS) $(BLDROOT)/concorde.a $(OBJS)
$(RANLIB) $(BLDROOT)/concorde.a
include ../INCLUDE/Makefile.common
# DO NOT DELETE THIS LINE -- make depend depends on it.
I=$(CCINCDIR)
I2=$(BLDROOT)/INCLUDE
kd_main.$o: kd_main.c $(I)/machdefs.h $(I2)/config.h $(I)/util.h \
$(I)/kdtree.h
kdbuild.$o: kdbuild.c $(I)/machdefs.h $(I2)/config.h $(I)/util.h \
$(I)/kdtree.h $(I)/macrorus.h
kdnear.$o: kdnear.c $(I)/machdefs.h $(I2)/config.h $(I)/kdtree.h \
$(I)/util.h $(I)/macrorus.h
kdspan.$o: kdspan.c $(I)/machdefs.h $(I2)/config.h $(I)/kdtree.h \
$(I)/util.h $(I)/macrorus.h
kdtwoopt.$o: kdtwoopt.c $(I)/machdefs.h $(I2)/config.h $(I)/util.h \
$(I)/kdtree.h $(I)/macrorus.h
I have copied both of jconcorde_TSP.c and jconcorde_TSP.h into the KDTREE folder
what do I need to do in order to create the libtsp.dylib for the java code?
I have tried this:
gcc -g -O3 -arch x86_64 -I../INCLUDE -I../INCLUDE -I/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home//include -I/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home//include/darwin -c -dynamiclib -o libtsp.dylib jconcorde_TSP.c ../UTIL/util.a -lm
but after I copied the libtsp.dylib into the java project I get this exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /Users/home_pc/NetBeansProjects/JConcorde/libtsp.dylib: dlopen(/Users/home_pc/NetBeansProjects/JConcorde/libtsp.dylib, 1): no suitable image found. Did find:
/Users/home_pc/NetBeansProjects/JConcorde/libtsp.dylib: mach-o, but wrong filetype
/Users/home_pc/NetBeansProjects/JConcorde/libtsp.dylib: mach-o, but wrong filetype
at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2430)
at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2487)
at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2684)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2649)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:829)
at java.base/java.lang.System.loadLibrary(System.java:1867)
at jconcorde.TSP.<clinit>(TSP.java:15)
/Users/home_pc/NetBeansProjects/JConcorde/nbproject/build-impl.xml:1328: The following error occurred while executing this line:
/Users/home_pc/NetBeansProjects/JConcorde/nbproject/build-impl.xml:948: Java returned: 1
what am I doing wrong?
After a discussion in the comments with #P.N.N the solution was found.
The correct compilation command is:
gcc -g -O3 -arch x86_64 -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" -L"../UTIL" -I"../INCLUDE" -I"../" -dynamiclib -o libtsp.dylib jconcorde_TSP.c ../UTIL/util.a kdtree.a
Compared to the original command the solution was to add a library path adding -L"../UTIL" to the compilation and then add a missing static library to the command kdtree.a

How can I call a Go function from Java using the Java native interface?

It is possible to call C methods through the JNA interface in Java. How can I reach the same functionality with Go?
package main
import "fmt"
import "C"
//export Add
func Add(x, y int) int {
fmt.Printf("Go says: adding %v and %v\n", x, y)
return x + y
}
After review of the documentation about Go Shared Libraries:
It is possible to integrate the call of Go functions from Java Spring Batch. Below is a short example:
Go function:
package main
import "fmt"
import "C"
//export Add
func Add(x, y int) int {
fmt.Printf("Go says: adding %v and %v\n", x, y)
return x + y
}
After that, execute the command to generate the binary files:
go build -buildmode=c-shared -o bin/lib-cqm-transformer.so src/cqm_transformer.go
This generates the binary files:
ls -la bin/
total 2860
drwxrwxr-x 2 dmotta dmotta 4096 abr 23 01:13 .
drwxrwxr-x 5 dmotta dmotta 4096 abr 23 00:35 ..
-rw-r--r-- 1 root root 1558 abr 23 01:13 lib-cqm-transformer.h
-rw-r--r-- 1 root root 2915112 abr 23 01:13 lib-cqm-transformer.so
Finally, create the JNA class:
package com.XX.XX.batch.engine.transformer;
import com.sun.jna.Library;
import com.sun.jna.Native;
public class GoEngineTransformerTest {
static GoCqmTransformer GO_CQM_TRANSFORMER;
static {
String os = System.getProperty("os.name").toLowerCase();
String libExtension;
if (os.contains("mac os")) {
libExtension = "dylib";
} else if (os.contains("windows")) {
libExtension = "dll";
} else {
libExtension = "so";
}
String pwd = System.getProperty("user.dir");
String lib = pwd + "/golang/bin/lib-cqm-transformer." + libExtension;
GO_CQM_TRANSFORMER = (GoCqmTransformer) Native.loadLibrary(lib, GoCqmTransformer.class);
}
public interface GoCqmTransformer extends Library {
long Add(long x, long y);
}
public static void main(String[] args) {
System.out.println("Java says: about to call Go ..");
long total = GO_CQM_TRANSFORMER.Add(30, 12);
System.out.println("Java says: result is " + total);
}
}
After that, execute from the main Java class. Results:
Java HotSpot(TM) 64-Bit Server VM warning: You have loaded library /tmp/jna1412558273325390219.tmp which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.
Java says: about to call Go ..
Go says: adding 30 and 12
Java says: result is 42

Updating module version when updating version in dependencies (multi-module maven )

My problem: versions-maven-plugin helps me to up version in some module (let's call it A) in my multi-module maven project.
Some modules (let's call it B and C) in this project have in dependencies module A. I need to up versions for this modules (B and C) too. Sometimes, i also need to up version in other module (B-parent) where B (or C) in dependencies (A version up -> B version up -> B-parent version up). Other problem is the modules can be at different levels of nesting.
Example:
root:
---B-parent:
---B (A in dependencies)
---C-parent
---C (A in dependencies)
---A-parent:
---A
Process: A version up -> A-parent version up, C version-up -> C-parent version-up, B version-up -> B-parent version up.
This plugin can't do this.
Is there any idea how this can be done?
Or my strategy of updating versions is not good enough?
I've made a script for increasing version numbers in all dependent modules recursively with a versions-maven-plugin.
Algorithm is as follows:
Run versions:set in target module
Run versions:set in all modules which have been updated by versions:set from previous step. If the module has been already processed - skip it.
Repeat step 2
Python 2.7 code
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
# How To
#
# Run script and pass module path as a first argument.
# Or run it without arguments in module dir.
#
# Script will request the new version number for each module.
# If no version provided - last digit will be incremented (1.0.0 -> 1.0.1).
# cd <module-path>
# <project-dir>/increment-version.py
# ...
# review changes and commit
from subprocess import call, Popen, PIPE, check_output
import os
import re
import sys
getVersionCommand = "mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate " \
"-Dexpression=project.version 2>/dev/null | grep -v '\['"
def getCurrentModuleVersion():
return check_output(getVersionCommand, shell=True).decode("utf-8").split("\n")[0]
def incrementLastDigit(version):
digits = version.split(".")
lastDigit = int(digits[-1])
digits[-1] = str(lastDigit+1)
return ".".join(digits)
def isUpdatedVersionInFile(version, file):
return "<version>" + version + "</version>" in \
check_output("git diff HEAD --no-ext-diff --unified=0 --exit-code -a --no-prefix {} "
"| egrep \"^\\+\"".format(file), shell=True).decode("utf-8")
def runVersionSet(version):
process = Popen(["mvn", "versions:set", "-DnewVersion="+version, "-DgenerateBackupPoms=false"], stdout=PIPE)
(output, err) = process.communicate()
exitCode = process.wait()
if exitCode is not 0:
print "Error setting the version"
exit(1)
return output, err, exitCode
def addChangedPoms(version, dirsToVisit, visitedDirs):
changedFiles = check_output(["git", "ls-files", "-m"]) \
.decode("utf-8").split("\n")
changedPoms = [f for f in changedFiles if f.endswith("pom.xml")]
changedDirs = [os.path.dirname(os.path.abspath(f)) for f in changedPoms if isUpdatedVersionInFile(version, f)]
changedDirs = [d for d in changedDirs if d not in visitedDirs and d not in dirsToVisit]
print "New dirs to visit:", changedDirs
return changedDirs
if __name__ == "__main__":
visitedDirs = []
dirsToVisit = []
if len(sys.argv) > 1:
if os.path.exists(os.path.join(sys.argv[1], "pom.xml")):
dirsToVisit.append(os.path.abspath(sys.argv[1]))
else:
print "Error. No pom.xml file in dir", sys.argv[1]
exit(1)
else:
dirsToVisit.append(os.path.abspath(os.getcwd()))
pattern = re.compile("aggregation root: (.*)")
while len(dirsToVisit) > 0:
dirToVisit = dirsToVisit.pop()
print "Visiting dir", dirToVisit
os.chdir(dirToVisit)
currentVersion = getCurrentModuleVersion()
defaultVersion = incrementLastDigit(currentVersion)
version = raw_input("New version for {}:{} ({}):".format(dirToVisit, currentVersion, defaultVersion))
if not version.strip():
version = defaultVersion
print "New version:", version
output, err, exitcode = runVersionSet(version)
rootDir = pattern.search(output).group(1)
visitedDirs = visitedDirs + [dirToVisit]
os.chdir(rootDir)
print "Adding new dirs to visit"
dirsToVisit = dirsToVisit + addChangedPoms(version, dirsToVisit, visitedDirs)

Categories

Resources