corretto / corretto-8

Amazon Corretto 8 is a no-cost, multi-platform, production-ready distribution of OpenJDK 8
GNU General Public License v2.0
2.11k stars 221 forks source link

Adding client location for jvm.dll for Windows X86-32 #284

Open tm250486 opened 3 years ago

tm250486 commented 3 years ago

Hello,

Is your feature request related to a problem?

We are migrating from Oracle JDK 8 to Corretto JDK8. In Corretto x86, there are only jvm.dll in bin/server. But our apps require a bin/client version in order to work.

Describe a solution you would like

A client/jvm.dll in both JDK x86 (jre/bin/client/jvm.dll) and JRE x86 (bin/client/jvm.dll).

A server/jvm.dll in JDK x86

Set RuntimeLib from bin\server to bin\client in x86 version.

navyxliu commented 3 years ago

Thank you for using corretto-8. I still have a question about it. Do you want to a client JVM or you can only load client library in your application?

I understand that server/libjvm.dll is big. Some embedded systems may not load it because of resource constraints. Currently, we don't build client version of hotspot because it is less popular in use. If you just need a client JVM version, we can help you by trimming down feature set from the server jvm.

tm250486 commented 3 years ago

Thank you for your response.

Yes, I want a client JVM for my application as it's better for our application. But for now for testing, can you give me these options to launch corretto jvm in 'client' version?

tm250486 commented 3 years ago

I'm not too familiar with Java. For more information: our applications has to work in old machines with very limited resource contraints. By default, we put

Also, correct me if I'm wrong, but the JNI integration has to work with 'client' JVM?

navyxliu commented 3 years ago

Understand. You need to shrink your memory footprint to fix your environment.

'java -client' can't give you so-called client jvm now. Disabling tieredCompilation should give you the ballpark. please refer to the answer here: https://github.com/corretto/corretto-8/issues/172#issuecomment-542960592

If you observe that jvm consumes too many CPU , you may also consider to disable the server compiler but only use the client JIT compiler.

-XX:ReservedCodeCacheSize=12M -XX:TieredStopAtLevel=1

tm250486 commented 3 years ago

Thank you for your help.

With -XX:-TieredCompilation, we observe in VisualVM that memory reduces to normal level. One of our application works now.

But another one can't seem to work with Server mode at all. It keeeps hanging randomly and we have to kill and restart this application.

For more context, I tried with OracleJDK -server option and I succeed to reproduce problem. In full client mode (without C2 flags and all), no problem at all!

tm250486 commented 3 years ago

For a quick update:

We found out that our JNI calls from Java to a C++ DLL are the one that makes our application hanging. It's just so weird that these calls work with client option but not server. I tried googling but no result.

Do you have any idea?

davecurrie commented 3 years ago

Can you share that DLL and/or source?

simonis commented 3 years ago

Thank you for your help.

With -XX:-TieredCompilation, we observe in VisualVM that memory reduces to normal level. One of our application works now.

But another one can't seem to work with Server mode at all. It keeeps hanging randomly and we have to kill and restart this application.

For more context, I tried with OracleJDK -server option and I succeed to reproduce problem. In full client mode (without C2 flags and all), no problem at all!

Notice that with -XX:-TieredCompilation alone you'll still using the C2, "server" JIT compiler which has higher resource consumption compared to the C1, "client" JIT. As @navyxliu already recommanded, you should use -XX:TieredStopAtLevel=1. For small heaps and minimal footprint it also makes sense to use -XX:+UseSerialGC.

simonis commented 3 years ago

For a quick update:

We found out that our JNI calls from Java to a C++ DLL are the one that makes our application hanging. It's just so weird that these calls work with client option but not server. I tried googling but no result.

Do you have any idea?

So just to be sure:

tm250486 commented 3 years ago

@davecurrie unfortunately I can't share DLL or source as it's confidential. I will try to have a reproducible case. @simonis Yes as you said, our application can work with OracleJDK8 -client option but not server option. For Corretto8, well these options can't be used anyway as Corretto doesn't support a 'client' jdk.

tm250486 commented 3 years ago

Hello and happy new year!

More update: I found where in our C++ DLL the problem lied. We have a piece of code that monitor exception from all sources and do the call stack (using a Window callback AddVectoredExceptionHandler).

As it turned out for some reason in some exception stacks, EBP points to an invalid memory (outside of thread stack) and our exception handler doesn't like that and it causes the hanging problem. For now, I just disable the exception handler when EBP is invalid and our applicaions work now :). For now we just test to see if this change impacts others parts of our code.

Still, it does feel strange that there is no problem with Java client but only Java server. Curiously, I tried AdoptOpenJDK and this JDK works in server mode with no change in our code.

You can found the thread dump here if you need more informations: jDumpAll9.txt

The stack which hangs is:

----------------- 1 ----------------- 0x432cd62c LisaToolsJNI!CallStack::walk + 0x98 0x432bc3b4 LisaToolsJNI!ThreadContext::setExceptionCallStack + 0x48 0x432d04a3 LisaToolsJNI!handleVectoredException + 0x54 0x77c8b8b8 ntdll!LdrSetDllManifestProber + 0xf8 0x77c8859b ntdll!RtlUnwind + 0x1cb 0x77c93b36 ntdll!KiUserExceptionDispatcher + 0x26 Locked ownable synchronizers:

  • None
simonis commented 3 years ago

Notice that there's no guarantee that JIT-compiled frames adhere to the platform ABI. Methods compiled by the C2 "server" JIT compiler use EBP as a general purpose register. You therefore can't easily walk a Java stack which contains generated code. You can try to use the -XX:+PreserveFramePointer command line option to instruct C2 to leave EBP as frame pointer to improve the situation. But there might still be frames (e.g. generated stubs) which you can't easily walk manually. This is a well known problem for runtimes like the JDK which do a lot of dynamic code generation. If you're interested in the topic you can have a look at the https://github.com/jvm-profiling-tools/async-profiler project to see how they solve the problem.