Java Breakpoint set on java.lang.ref.Finalizer not stopped - java

I want to get some insights of Java java.lang.ref.Finalizer initializing process so I set a breakpoint on its class static block:
static {
-> ThreadGroup tg = Thread.currentThread().getThreadGroup(); // breakpoint set on this line
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread finalizer = new FinalizerThread(tg);
finalizer.setPriority(Thread.MAX_PRIORITY - 2);
finalizer.setDaemon(true);
finalizer.start();
}
Then start an empty main() method via IntelliJ IDEA debug button, but the breakpoint never stops the program (JVM just executes to its end and exits.)
Java version:
openjdk version "1.8.0_302"
OpenJDK Runtime Environment Corretto-8.302.08.1 (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM Corretto-8.302.08.1 (build 25.302-b08, mixed mode)
Why this breakpoint not taking effect?

Since JDK 5.0, the JVM debugging capability has been constructed based on JVM TI which replaces the JVMPI and JVMDI. I'm not familiar with JVMDI thus the following statements are based on the fact you debug the code using agentlib:jdwp like:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
The jdwp agent (loaded from libjdwp.so file) bind the port specified (5005 in the above example) on receiving post_vm_initialized event. As the event name indicates, VM has been initialized and the Finalizer class has already been loaded when the debug port binding happens (of course you can only debug Java codes after JDWP port listening). So you cannot debug the static block code of Finalizer. In fact, classes loaded before JDWP port binding all are not debuggable in terms of initialization. But if thread runs in the code of the loaded-before classes afterwards, you're still able to debug it, for example the Finalizer.FinalizerThread#run method.
I found a quote from The JVM Tool Interface (JVM TI): How VM Agents Work:
The library is loaded before the VM has initialized, allowing the agent library to capture early VM events that it could not access before.
JDWP agentlib may bind the port on the other hand in Agent_Onload function (in debugInit.c), which may allow the debugging for all classes loading in JVM (I guess).
PS: if you are interested in the code mentioned above (in OpenJDK 8 with Mercurial ID dcb218f54ca1):
post_vm_initialized event processing in function debugInit.c:initialize.
JDWP's Agent_Onload function also locates in code file debugInit.c.

Related

JNI - is there a way to get JNI_OnUnload to be called by the JVM?

There is very little information about this, for example this from 2006, and people giving up on releasing JNI resources gracefully.
JNI_OnUnload (Oracle doc) is meant for releasing resources ("global refs" in particular) when your native functionality is no longer needed from within the JVM. A native library would be loaded like this
static {
System.loadLibrary("mylibjni"); // on Linux this translates to "libmylibjni.so"
}
... but Java offers no explicit way for unloading.
What happens: in my lib, because of not being given the opportunity to cleanup, the lib does eventually unload (I don't understand when, see below call stack), but too late, this triggers some global variables owning JNI global refs to call DeleteGlobalRef unsuccessfully:
# JRE version: OpenJDK Runtime Environment (10.0.2+13) (build 10.0.2+13)
# Java VM: OpenJDK 64-Bit Server VM (10.0.2+13, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C [libblahjni.so+0x9a7e6] JNIEnv_::DeleteGlobalRef(_jobject*)+0x14
Digging into it, this is because of not having a JNIEnv on the thread doing the unloading (I'm caching the env on a thread_local basis). Trying to retrieve the Env at that time hasn't worked - I tried using JavaVM::GetEnv and JavaVM::AttachCurrentThread and it seems even though attaching works fine, JavaVM::GetEnv keeps returning JNI_EDETACHED (-2). So presumably, it's too late in the JVM lifecycle to attach/have an env anymore.
Something else I've tried - as per 2006 article above, in Java I tried doing System.runFinalizersOnExit(true), without luck. Even though I do see finalizers being invoked (as opposed to when not invoking runFinalizers, see below output), JNI_OnUnload is still not called.
Checked JNI functions are being used to validate JNI usage
[Dynamic-linking native method java.lang.Shutdown.runAllFinalizers ... JNI]
Checked JNI functions are being used to validate JNI usage
[Dynamic-linking native method java.lang.Shutdown.halt0 ... JNI]
As last piece of info, the lib unloading call stack looks like this. I don't understand where it's coming from. I'm on latest Arch linux, Java 10, I'm running in Docker if that matters. I'd like to sort out graceful exit principially and because that gives confidence that you are spotting problems occurring later in the project lifecycle, with ease.
[Dynamic-linking native method java.lang.Shutdown.runAllFinalizers ... JNI]
Checked JNI functions are being used to validate JNI usage
[Dynamic-linking native method java.lang.Shutdown.halt0 ... JNI]
0# (some more code of my own ommitted at the top of the stack)
1# std::_Optional_payload<...
2# std::_Optional_base<...
3# std::optional<...>::~optional() in /orion/mpf-jni/Debug/libmylibjni.so
4# 0x00007FDCEC5E845C in /usr/lib/libc.so.6
5# 0x00007FDCEC5E858E in /usr/lib/libc.so.6
6# 0x00007FDCEB919B89 in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
7# 0x00007FDCEBDF58C6 in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
8# 0x00007FDCEBDF5346 in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
9# 0x00007FDCEBDF2770 in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
10# 0x00007FDCEBDF3D2F in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
11# 0x00007FDCEBDF3FBE in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
12# 0x00007FDCEBC0558A in /usr/lib/jvm/java-10-openjdk/lib/server/libjvm.so
13# 0x00007FDCEC378A9D in /usr/lib/libpthread.so.0
14# clone in /usr/lib/libc.so.6
1447612069173.971 Fatal| could not get JVM env object for JNI version [65540], error [-2]

Cassandra start error with ThreadPriorityPolicy=42

When I am trying to start Cassandra it shows me error like this I already did changes in the conf file also in env.sh, the file also.
No options of similar type error is working for this.
intx ThreadPriorityPolicy=42 is outside the allowed range [ 0 ... 1 ]
Improperly specified VM option 'ThreadPriorityPolicy=42'
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Other Information
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
This is a known issue of Cassandra - CASSANDRA-13107.
Before Java 9 JVM accepted any integer value for ThreadPriorityPolicy, while 0 and 1 were the only valid values.
ThreadPriorityPolicy=1 allows to raise thread priorities, but only if the process starts with root privileges. When ThreadPriorityPolicy=1, JVM explicitly checks that euid=0:
static int prio_init() {
if (ThreadPriorityPolicy == 1) {
// Only root can raise thread priority. Don't allow ThreadPriorityPolicy=1
// if effective uid is not root. Perhaps, a more elegant way of doing
// this is to test CAP_SYS_NICE capability, but that will require libcap.so
if (geteuid() != 0) {
if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) {
warning("-XX:ThreadPriorityPolicy requires root privilege on Linux");
}
ThreadPriorityPolicy = 0;
}
}
Note a bug (or backdoor) in the above code: if you set ThreadPriorityPolicy to something other than 0 or 1, euid check will be skipped, but the application will be still allowed to use priorities above normal. Cassandra uses this backdoor.
As a result of JEP 245 JDK 9 improved command line argument validation, and therefore ThreadPriorityPolicy does not accept values other than 0 or 1 anymore.
How to fix
Edit %CASSANDRA_HOME%/conf/jvm.options file:
If you run Cassandra under root on Linux,
replace -XX:ThreadPriorityPolicy=42 with -XX:ThreadPriorityPolicy=1
Otherwise remove -XX:ThreadPriorityPolicy=42 line altogether.
As the exception message is already telling you, the ThreadPriorityPolicy must be between 0 and 1:
intx ThreadPriorityPolicy=42 is outside the allowed range [ 0 ... 1 ]
Did you use Gateling? Than this might help you: https://github.com/gatling/gatling/issues/2950 (issue is resolved since Gatling 2.2).
It might be also worth checking if on your OS this setting makes sense at all. The meaning of this setting is somewhat like this:
0 : Normal. VM chooses priorities that are appropriate for normal applications. On Solaris NORM_PRIORITY and above are mapped to normal native priority. Java priorities below NORM_PRIORITY" map to lower native priority values. On Windows applications" are allowed to use higher native priorities. However, with ThreadPriorityPolicy=0, VM will not use the highest possible" native priority, THREAD_PRIORITY_TIME_CRITICAL, as it may interfere with system threads. On Linux thread priorities are ignored because the OS does not support static priority in SCHED_OTHER scheduling class which is the only choice for" non-root, non-realtime applications. 1 : Aggressive. Java thread priorities map over to the entire range of native thread priorities. Higher Java thread priorities map to higher native thread priorities. This policy should be used with care, as sometimes it can cause performance degradation in the application and/or the entire system. On Linux this policy requires root privilege.
If there is no $CASSANDRA_HOME setup as it was not a source install, then it can likely be under /usr/local/etc/cassandra
janani#janani-C02Z78CMLVDQ fievel % find / -name jvm.options
find: /usr/sbin/authserver: Permission denied
/usr/local/etc/cassandra/jvm.options
In my local, it was not under cassandra install path.
janani#janani-C02Z78CMLVDQ fievel % brew --prefix cassandra
/usr/local/opt/cassandra
janani#janani-C02Z78CMLVDQ fievel % ls /usr/local/opt/cassandra
CHANGES.txt LICENSE.txt NOTICE.txt homebrew.mxcl.cassandra.plist share
INSTALL_RECEIPT.json NEWS.txt bin libexec
janani#janani-C02Z78CMLVDQ fievel % find /usr/local/opt/cassandra -name jvm.options
janani#janani-C02Z78CMLVDQ fievel %

Java HotSpot(TM) 64-Bit Server VM warning Cannot open file logs/gc.log due to No such file or directory

I'm getting this error when I try to run
RACK_ENV=test be rails test test/system/service_provider_map_test.rb —seed 48088
Java HotSpot(TM) 64-Bit Server VM warning: Cannot open file logs/gc.log due to No such file or directory
The tests are then timing out with this error
Timeout while waiting for cluster status [green] and [1] nodes
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:551:in sleep': execution expired (Timeout::Error) from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:551:inblock (2 levels) in __wait_for_status' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:542:in loop' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:542:inblock in __wait_for_status' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/2.4.0/timeout.rb:108:in
timeout' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:541:in__wait_for_status' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:364:in wait_for_green' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:280:instart' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/elasticsearch-extensions-0.0.26/lib/elasticsearch/extensions/test/cluster.rb:52:in
start' from
/Users/patrickward/Desktop/esh/SDR/test/support/elasticsearch_helpers.rb:38:in
start_elasticsearch' from
/Users/patrickward/Desktop/esh/SDR/test/application_system_test_case.rb:12:in
<class:ApplicationSystemTestCase>' from
/Users/patrickward/Desktop/esh/SDR/test/application_system_test_case.rb:6:in
' from
/Users/patrickward/Desktop/esh/SDR/test/system/service_provider_map_test.rb:2:in
require' from
/Users/patrickward/Desktop/esh/SDR/test/system/service_provider_map_test.rb:2:in
' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/test_unit/test_requirer.rb:14:in
require' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/test_unit/test_requirer.rb:14:in
block in require_files' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/test_unit/test_requirer.rb:13:in
each' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/test_unit/test_requirer.rb:13:in
require_files' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/test_unit/minitest_plugin.rb:96:in plugin_rails_init' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.11.3/lib/minitest.rb:81:in
block in init_plugins' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.11.3/lib/minitest.rb:79:in
each' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.11.3/lib/minitest.rb:79:in
init_plugins' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.11.3/lib/minitest.rb:130:in
run' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/test_unit/minitest_plugin.rb:77:inrun' from
/Users/patrickward/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.11.3/lib/minitest.rb:63:in
`block in autorun'
For context: I'm running on a Mac OS, any help would be greatly appreciated
Java HotSpot(TM) 64-Bit Server VM warning: Cannot open file logs/gc.log due to No such file or directory
is not an error it is a warning and misleading. The real error message is
Timeout while waiting for cluster status [green] and [1] nodes
elasticsearch-ruby library has a test code which is starting a cluster itself.
and it comes from this test. https://github.com/elastic/elasticsearch-ruby/blob/6.x/elasticsearch-extensions/lib/elasticsearch/extensions/test/cluster.rb Line : 579
message = "\nTimeout while waiting for cluster status [#{status}]"
message += " and [#{arguments[:number_of_nodes]}] nodes" if arguments[:number_of_nodes]
__log message.ansi(:red, :bold)
However there was a bug which is pointing your problem.
https://github.com/elastic/elasticsearch-ruby/issues/371
You may need to upgrade your elasticsearch-ruby version to newer one

How to find out the name of JIT used when you run your java program

Is there any command or something like that to know the name of JIT used when running the java program?
(This answer applies to OpenJDK Hotspot)
You should be able to use -XX:+LogCompilation to get a log file(hotspot_pid< PID>.log, in the startup directory) containing lines like
<nmethod compile_id='2' compiler='C1' level='3' ...
Note:LogCompilation is a diagnostic VM-option. So you will need to enable it by preceding it with
-XX:+UnlockDiagnosticVMOptions. Your script line for running the class file would look like:
java -XX:+UnlockDiagnosticVMOptions -XX:LogCompilation MyClass
Note that there may be several different JITs in action during one execution.

Can't run JDI trace example: Error: Could not find or load main class

I run in command line the following program as an example app:
java -cp "D:\projects\PDFJavaFX\lib\PDFRenderer-0.9.1.jar"
com/sun/pdfview/PDFViewer
Then I run in command line the JDI trace example:
java -cp "C:\Program
Files\Java\jdk1.7.0_13\lib\tools.jar;D:\projects\JDI_Trace\jar\trace.jar;D:\projects\PDFJavaFX\lib\PDFRenderer-0.9.1.jar"
com/sun/tools/example/trace/Trace com/sun/pdfview/PDFViewer
I get this error:
Error: Could not find or load main class com.sun.pdfview.PDFViewer
-- VM Started --
-- The application exited --
The example app runs correctly, and it is included in the classpath.
What's the cause of this?
What am I missing?
Thanks
Edit: It looks like it is classpath related.
I did get this to work (well, it popped up the GUI but then crashed pretty quickly). I used the classpath environment variable instead of -cp:
C:\cos126\dev\debug>set CLASSPATH=%CLASSPATH%;c:\tmp\PDFRenderer-0.9.1.jar;c:\tmp\debug
So, not pretty, but then it did work. So it looks like the newly created VM doesn't automatically inherit -cp. I am optimistic, but not sure, that there might be an option you can change when starting the new VM to do this for you. To see the "documentation" for the VM launching options, you can add some code like
for (Map.Entry<String, Connector.Argument> arg : arguments.entrySet()) {
System.out.println(arg.getValue().name()+" "+arg.getValue().description());
}
to Trace.java. When I do this, it prints out
home Home directory of the SDK or runtime environment used to launch the application
options Launched VM options
main Main class and arguments, or if -jar is an option, the main jar file and arguments
suspend All threads will be suspended before execution of main
quote Character used to combine space-delimited text into a single command line argument
vmexec Name of the Java VM launcher
so maybe one of those is useful? Good luck!
By the way, this is what I used JDI for:
http://cscircles.cemc.uwaterloo.ca/java-visualize/
I am in the process of making the source shareable, if you want to see it (although I'm not 100% sure it will be of use).
Your command :
java -cp "C:\Program Files\Java\jdk1.7.0_13\lib\tools.jar;
D:\projects\JDI_Trace\jar\trace.jar;
D:\projects\PDFJavaFX\lib\PDFRenderer-0.9.1.jar"
com/sun/tools/example/trace/Trace com/sun/pdfview/PDFViewer
Explanation :
The new VM which is created by the Trace has different class path. main class PDFViewer is in the PDFRenderer**.jar,but the new VM didn't know the jar, so it can't find the main class. I also met this problem when I used Eclipse. And by changing the working directory, I can run it successfully.
In fact, the Trace class uses JDI to launch the new VM, but it only set the main option and discard the vm options. The code below is quoted from the Thrace class source file, and I add some lines to print the options.
Map<String, Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
Map<String, Connector.Argument> arguments = connector.defaultArguments();
Connector.Argument mainArg =
(Connector.Argument)arguments.get("main");
//added by me: begin
java.util.Set<String> argsString = arguments.keySet();
System.out.println("connector args size is :" + argsString.size());
for (String arg : argsString) {
System.out.println(arg + "=="+ arguments.get(arg).description()+"=="+arguments.get(arg).value()) ;
//added by me: end
}
if (mainArg == null) {
throw new Error("Bad launching connector");
}
mainArg.setValue(mainArgs);
The output of the arguments size is 6, and they are "home, options, main, suspend, quote and vmexec". If we want to configure the new VM options, we can set the "options" by setValue method like setting "main".

Categories

Resources