From e806f87f9cb0b4a48298370f813a76b5e24039b4 Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Sun, 8 Mar 2020 11:32:00 +0100 Subject: [PATCH 1/3] Update Java Memory Assistant Update Java Memory Assistant to version 0.4.0, which adds support for the following JVMs: - AdoptOpenJDK HotSpot 8.x - AdoptOpenJDK HotSpot 11.x - OpenJDK 11.x - Oracle JVM 11.x - Pivotal JDK 8.x - SAP Machine 11.x On Java 9+, an exception to the Java Module system must be added (--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED) to allow access to com.sun.management.HotSpotDiagnosticMXBean, which is needed to created heapdumps in live mode. --- docs/framework-java_memory_assistant.md | 7 ++++ .../framework/java_memory_assistant/agent.rb | 8 ++++ .../java_memory_assistant/agent_spec.rb | 41 ++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/docs/framework-java_memory_assistant.md b/docs/framework-java_memory_assistant.md index 6612aab909..f8a2f60594 100644 --- a/docs/framework-java_memory_assistant.md +++ b/docs/framework-java_memory_assistant.md @@ -46,6 +46,13 @@ The timestamp pattern `%ts:yyyyMMdd'T'mmssSSSZ%` is equivalent to the `%FT%T%z` | Eden | `eden` | | Survivor | `survivor` | | Old Generation | `old_gen` | +| Tenured Gen | `tenured_gen` | +| CodeHeap 'non-nmethods' | `code_heap.non_nmethods` | +| CodeHeap 'profiled nmethods' | `code_heap.profiled_nmethods` | +| CodeHeap 'non-profiled nmethods' | `code_heap.non_profiled_nmethods` | + +Different builds and versions of Java Virtual Machines offer different memory areas. +The list of supported Java Virtual Machines and the respective memory areas can be found in the [Java Memory Assistant documentation](https://github.com/SAP/java-memory-assistant#supported-jvms). The default values can be found in the [`config/java_memory_assistant.yml`][] file. diff --git a/lib/java_buildpack/framework/java_memory_assistant/agent.rb b/lib/java_buildpack/framework/java_memory_assistant/agent.rb index 89054fc542..aeb8ffcff6 100644 --- a/lib/java_buildpack/framework/java_memory_assistant/agent.rb +++ b/lib/java_buildpack/framework/java_memory_assistant/agent.rb @@ -42,6 +42,14 @@ def release .add_system_property('jma.heap_dump_name', %("#{name_pattern}")) .add_system_property 'jma.log_level', normalized_log_level + if @droplet.java_home.java_9_or_later? + # Enable access to com.sun.management.HotSpotDiagnosticMXBean to circumvent + # Java modules limitations in Java 9+ + # See https://github.com/SAP/java-memory-assistant#running-the-java-memory-assistant-on-java-11 + @droplet.java_opts + .add_preformatted_options('--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED') + end + add_system_prop_if_config_present 'check_interval', 'jma.check_interval' add_system_prop_if_config_present 'max_frequency', 'jma.max_frequency' diff --git a/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb b/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb index 84564840ea..2f3605917c 100644 --- a/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb +++ b/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb @@ -52,6 +52,8 @@ it 'updates JAVA_OPTS with default values' do component.release + expect(java_opts).not_to include('--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED') + expect(java_opts).to include('-javaagent:$PWD/.java-buildpack/java_memory_assistant_agent/' \ 'java-memory-assistant-1.2.3.jar') expect(java_opts).to include('-Djma.enabled=true') @@ -61,6 +63,43 @@ expect(java_opts).to include('-Djma.thresholds.heap=90') expect(java_opts).to include('-Djma.thresholds.old_gen=90') + + end + + context do + + let(:java_home_delegate) do + delegate = JavaBuildpack::Component::MutableJavaHome.new + delegate.root = app_dir + '.test-java-home' + delegate.version = JavaBuildpack::Util::TokenizedVersion.new('1.8.0_55') + + delegate + end + + it 'it does not add the --add-opens on Java 8' do + component.release + + expect(java_opts).not_to include('--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED') + end + + end + + context do + + let(:java_home_delegate) do + delegate = JavaBuildpack::Component::MutableJavaHome.new + delegate.root = app_dir + '.test-java-home' + delegate.version = JavaBuildpack::Util::TokenizedVersion.new('9.0.1') + + delegate + end + + it 'adds the --add-opens on Java 11' do + component.release + + expect(java_opts).to include('--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED') + end + end end @@ -200,7 +239,7 @@ end it 'falls back on JBP log_level when no log_level specified via configuration', - :enable_log_file, log_level: 'WARN' do + :enable_log_file, log_level: 'WARN' do component.release expect(java_opts).to include('-Djma.log_level=WARNING') From e572d7f148902f31db7bfae35f1ac883dbecae07 Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Mon, 16 Mar 2020 20:44:58 +0100 Subject: [PATCH 2/3] Quote arguments that could have special chars for BASH --- .../framework/java_memory_assistant/agent.rb | 7 ++- .../java_memory_assistant/agent_spec.rb | 46 ++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/java_buildpack/framework/java_memory_assistant/agent.rb b/lib/java_buildpack/framework/java_memory_assistant/agent.rb index aeb8ffcff6..bd0a14fbdd 100644 --- a/lib/java_buildpack/framework/java_memory_assistant/agent.rb +++ b/lib/java_buildpack/framework/java_memory_assistant/agent.rb @@ -51,12 +51,15 @@ def release end add_system_prop_if_config_present 'check_interval', 'jma.check_interval' - add_system_prop_if_config_present 'max_frequency', 'jma.max_frequency' + + if @configuration.key?('max_frequency') + @droplet.java_opts.add_preformatted_options "'-Djma.max_frequency=#{@configuration['max_frequency']}'" + end return unless @configuration.key?('thresholds') @configuration['thresholds'].each do |key, value| - @droplet.java_opts.add_system_property "jma.thresholds.#{key}", value.to_s + @droplet.java_opts.add_preformatted_options "'-Djma.thresholds.#{key}=#{value.to_s}'" end end diff --git a/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb b/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb index 2f3605917c..30161eec10 100644 --- a/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb +++ b/spec/java_buildpack/framework/java_memory_assistant/agent_spec.rb @@ -59,10 +59,10 @@ expect(java_opts).to include('-Djma.enabled=true') expect(java_opts).to include('-Djma.check_interval=5s') - expect(java_opts).to include('-Djma.max_frequency=1/1m') + expect(java_opts).to include('\'-Djma.max_frequency=1/1m\'') - expect(java_opts).to include('-Djma.thresholds.heap=90') - expect(java_opts).to include('-Djma.thresholds.old_gen=90') + expect(java_opts).to include('\'-Djma.thresholds.heap=90\'') + expect(java_opts).to include('\'-Djma.thresholds.old_gen=90\'') end @@ -132,15 +132,15 @@ 'java-memory-assistant-0.1.0.jar') expect(java_opts).to include('-Djma.enabled=true') expect(java_opts).to include('-Djma.check_interval=10m') - expect(java_opts).to include('-Djma.max_frequency=4/10h') + expect(java_opts).to include('\'-Djma.max_frequency=4/10h\'') expect(java_opts).to include('-Djma.log_level=DEBUG') - expect(java_opts).to include('-Djma.thresholds.heap=60') - expect(java_opts).to include('-Djma.thresholds.code_cache=30') - expect(java_opts).to include('-Djma.thresholds.metaspace=5') - expect(java_opts).to include('-Djma.thresholds.perm_gen=45.5') - expect(java_opts).to include('-Djma.thresholds.eden=90') - expect(java_opts).to include('-Djma.thresholds.survivor=95.5') - expect(java_opts).to include('-Djma.thresholds.old_gen=30') + expect(java_opts).to include('\'-Djma.thresholds.heap=60\'') + expect(java_opts).to include('\'-Djma.thresholds.code_cache=30\'') + expect(java_opts).to include('\'-Djma.thresholds.metaspace=5\'') + expect(java_opts).to include('\'-Djma.thresholds.perm_gen=45.5\'') + expect(java_opts).to include('\'-Djma.thresholds.eden=90\'') + expect(java_opts).to include('\'-Djma.thresholds.survivor=95.5\'') + expect(java_opts).to include('\'-Djma.thresholds.old_gen=30\'') end end @@ -160,6 +160,30 @@ end + context do + let(:configuration) do + { + 'thresholds' => { + 'heap' => '>600MB', + 'eden' => '< 30MB' + } + } + end + + let(:version) { '0.1.0' } + + it 'escapses redirection characters' do + component.release + + expect(java_opts).to include('-javaagent:$PWD/.java-buildpack/java_memory_assistant_agent/' \ + 'java-memory-assistant-0.1.0.jar') + + expect(java_opts).to include('\'-Djma.thresholds.heap=>600MB\'') + expect(java_opts).to include('\'-Djma.thresholds.eden=< 30MB\'') + end + + end + context do let(:configuration) do { From 3b7ec53ca55505b5627dcc679b119dd092b2d58d Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Mon, 16 Mar 2020 21:17:34 +0100 Subject: [PATCH 3/3] Add configurability for new memory pools --- config/java_memory_assistant.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/java_memory_assistant.yml b/config/java_memory_assistant.yml index 2f94cf408a..9f4c874933 100644 --- a/config/java_memory_assistant.yml +++ b/config/java_memory_assistant.yml @@ -30,6 +30,11 @@ agent: eden: survivor: old_gen: ">600MB" + tenured_gen: + code_heap.non_nmethods: + code_heap.non_profiled_nmethods: + code_heap.profiled_nmethods: + clean_up: version: 0.+ repository_root: https://raw.githubusercontent.com/SAP/java-memory-assistant-tools/repository-cu