Skip to content

Commit 3528a37

Browse files
committed
Improve Java Opts Coherence
Previously, the way that JAVA_OPTS were handled was a bit inconsistent. First, JAVA_OPTS from the environment could be used to affect the memory calculator, but JAVA_OPTS from configuration could not due to the fact that they were assembled on the command line after the calculator had run. In addition, any changes to the environment's JAVA_OPTS would require a restage as those values were written into the command line instead of just being passed through the command stream. This change attempts to improve the consistency of how JAVA_OPTS are handled by doing two things. First, the environment's JAVA_OPTS are never processed as part of staging. Instead, a $JAVA_OPTS is appended (or not depending on configuration) to the JAVA_OPTS contributed to the buildpack. This solves the restage issue. Second, it declares the JAVA_OPTS as the very first part of the execution command, before the memory calculator. This solves the issue of ensuring that both environment and configured JAVA_OPTS are available to the memory calculator at startup. [#423][#424]
1 parent e0915ee commit 3528a37

24 files changed

+64
-168
lines changed

lib/java_buildpack/buildpack.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ def release
8181
component_detection('framework', @frameworks, false).map(&:release)
8282

8383
commands << container.release
84+
85+
commands.insert 0, @java_opts.as_env_var
8486
command = commands.flatten.compact.join(' && ')
8587

8688
payload = {
@@ -111,6 +113,8 @@ def initialize(app_dir, application)
111113
log_environment_variables
112114
log_application_contents application
113115

116+
@java_opts = Component::JavaOpts.new(app_dir)
117+
114118
mutable_java_home = Component::MutableJavaHome.new
115119
immutable_java_home = Component::ImmutableJavaHome.new mutable_java_home, app_dir
116120

@@ -120,7 +124,7 @@ def initialize(app_dir, application)
120124
'application' => application,
121125
'env_vars' => Component::EnvironmentVariables.new(app_dir),
122126
'extension_directories' => Component::ExtensionDirectories.new(app_dir),
123-
'java_opts' => Component::JavaOpts.new(app_dir),
127+
'java_opts' => @java_opts,
124128
'security_providers' => Component::SecurityProviders.new
125129
}
126130

lib/java_buildpack/container/dist_zip_like.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ def release
4242
[
4343
@droplet.environment_variables.as_env_vars,
4444
@droplet.java_home.as_env_var,
45-
@droplet.java_opts.as_env_var,
4645
'exec',
4746
qualify_path(start_script(root), @droplet.root)
4847
].flatten.compact.join(' ')

lib/java_buildpack/container/groovy.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def release
5454
[
5555
@droplet.environment_variables.as_env_vars,
5656
@droplet.java_home.as_env_var,
57-
@droplet.java_opts.as_env_var,
5857
'exec',
5958
qualify_path(@droplet.sandbox + 'bin/groovy', @droplet.root),
6059
@droplet.additional_libraries.as_classpath,

lib/java_buildpack/container/java_main.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ def release
7272

7373
def release_text(classpath)
7474
[
75-
@droplet.java_opts.as_env_var,
76-
'&&',
7775
@droplet.environment_variables.as_env_vars,
7876
'eval',
7977
'exec',

lib/java_buildpack/container/spring_boot_cli.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ def release
4949
[
5050
@droplet.environment_variables.as_env_vars,
5151
@droplet.java_home.as_env_var,
52-
@droplet.java_opts.as_env_var,
5352
'exec',
5453
qualify_path(@droplet.sandbox + 'bin/spring', @droplet.root),
5554
'run',

lib/java_buildpack/container/tomcat.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def command
3939
[
4040
@droplet.environment_variables.as_env_vars,
4141
@droplet.java_home.as_env_var,
42-
@droplet.java_opts.as_env_var,
4342
'exec',
4443
"$PWD/#{(@droplet.sandbox + 'bin/catalina.sh').relative_path_from(@droplet.root)}",
4544
'run'

lib/java_buildpack/framework/java_opts.rb

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,22 @@ class JavaOpts < JavaBuildpack::Component::BaseComponent
2626

2727
# (see JavaBuildpack::Component::BaseComponent#detect)
2828
def detect
29-
supports_configuration? || supports_environment? ? JavaOpts.to_s.dash_case : nil
29+
JavaOpts.to_s.dash_case
3030
end
3131

3232
# (see JavaBuildpack::Component::BaseComponent#compile)
3333
def compile; end
3434

3535
# (see JavaBuildpack::Component::BaseComponent#release)
3636
def release
37-
@droplet.java_opts.concat parsed_java_opts
37+
configured
38+
.shellsplit
39+
.map { |java_opt| /(?<key>.+?)=(?<value>.+)/ =~ java_opt ? "#{key}=#{escape_value(value)}" : java_opt }
40+
.each { |java_opt| @droplet.java_opts << java_opt }
41+
42+
@droplet.java_opts << '$JAVA_OPTS' if from_environment?
43+
44+
@droplet.java_opts.as_env_var
3845
end
3946

4047
private
@@ -43,39 +50,22 @@ def release
4350

4451
ENVIRONMENT_PROPERTY = 'from_environment'.freeze
4552

46-
ENVIRONMENT_VARIABLE = 'JAVA_OPTS'.freeze
47-
48-
private_constant :CONFIGURATION_PROPERTY, :ENVIRONMENT_PROPERTY, :ENVIRONMENT_VARIABLE
49-
50-
def parsed_java_opts
51-
parsed_java_opts = []
53+
private_constant :CONFIGURATION_PROPERTY, :ENVIRONMENT_PROPERTY
5254

53-
parsed_java_opts.concat @configuration[CONFIGURATION_PROPERTY].shellsplit if supports_configuration?
54-
parsed_java_opts.concat ENV[ENVIRONMENT_VARIABLE].shellsplit if supports_environment?
55-
56-
parsed_java_opts.map do |java_opt|
57-
if /(?<key>.+?)=(?<value>.+)/ =~ java_opt
58-
"#{key}=#{parse_shell_string(value)}"
59-
else
60-
java_opt
61-
end
62-
end
55+
def configured
56+
@configuration[CONFIGURATION_PROPERTY] || ''
6357
end
6458

65-
def parse_shell_string(str)
59+
def escape_value(str)
6660
return "''" if str.empty?
67-
str = str.dup
68-
str.gsub!(%r{([^A-Za-z0-9_\-.,:\/@\n$\\])}, '\\\\\\1')
69-
str.gsub!(/\n/, "'\n'")
70-
str
71-
end
7261

73-
def supports_configuration?
74-
@configuration.key?(CONFIGURATION_PROPERTY) && !@configuration[CONFIGURATION_PROPERTY].nil?
62+
str
63+
.gsub(%r{([^A-Za-z0-9_\-.,:\/@\n$\\])}, '\\\\\\1')
64+
.gsub(/\n/, "'\n'")
7565
end
7666

77-
def supports_environment?
78-
@configuration[ENVIRONMENT_PROPERTY] && ENV.key?(ENVIRONMENT_VARIABLE)
67+
def from_environment?
68+
@configuration[ENVIRONMENT_PROPERTY]
7969
end
8070

8171
end

lib/java_buildpack/jre/open_jdk_like_memory_calculator.rb

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ def compile
4343
memory_calculator.chmod 0o755
4444

4545
puts " Loaded Classes: #{class_count @configuration}, " \
46-
"Threads: #{stack_threads @configuration}, " \
47-
"JAVA_OPTS: '#{java_opts}'"
46+
"Threads: #{stack_threads @configuration}"
4847
end
4948
end
5049

@@ -53,13 +52,12 @@ def compile
5352
# @return [String] the memory calculation command
5453
def memory_calculation_command
5554
"CALCULATED_MEMORY=$(#{memory_calculation_string(@droplet.root)}) && " \
56-
'echo JVM Memory Configuration: $CALCULATED_MEMORY'
55+
'echo JVM Memory Configuration: $CALCULATED_MEMORY && ' \
56+
'JAVA_OPTS="$JAVA_OPTS $CALCULATED_MEMORY"'
5757
end
5858

5959
# (see JavaBuildpack::Component::BaseComponent#release)
60-
def release
61-
@droplet.java_opts.add_preformatted_options '$CALCULATED_MEMORY'
62-
end
60+
def release; end
6361

6462
protected
6563

@@ -85,10 +83,6 @@ def class_count(configuration)
8583
configuration['class_count'] || (0.35 * actual_class_count(root)).ceil
8684
end
8785

88-
def java_opts
89-
ENV['JAVA_OPTS']
90-
end
91-
9286
def memory_calculator
9387
@droplet.sandbox + "bin/java-buildpack-memory-calculator-#{@version}"
9488
end
@@ -104,7 +98,7 @@ def memory_calculation_string(relative_path)
10498
memory_calculation_string << "-stackThreads=#{stack_threads @configuration}"
10599
memory_calculation_string << "-loadedClasses=#{class_count @configuration}"
106100
memory_calculation_string << "-poolType=#{pool_type}"
107-
memory_calculation_string << "-vmOptions='#{java_opts}'" if java_opts
101+
memory_calculation_string << '-vmOptions="$JAVA_OPTS"'
108102

109103
memory_calculation_string.join(' ')
110104
end

lib/java_buildpack/util/play/post22.rb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,7 @@ def augment_classpath
3939

4040
# (see JavaBuildpack::Util::Play::Base#java_opts)
4141
def java_opts
42-
java_opts = @droplet.java_opts
43-
44-
java_opts.each do |option|
45-
next unless option.shellsplit.length > 1 && !bash_expression?(option)
46-
47-
raise "Invalid Java option contains more than one option: '#{option}'"
48-
end
49-
50-
java_opts.map { |option| option == '$CALCULATED_MEMORY' ? '${CALCULATED_MEMORY//-/-J-}' : "-J#{option}" }
42+
'${JAVA_OPTS//-/-J-}'
5143
end
5244

5345
# (see JavaBuildpack::Util::Play::Base#lib_dir)

lib/java_buildpack/util/play/pre22.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Pre22 < Base
2626

2727
# (see JavaBuildpack::Util::Play::Base#java_opts)
2828
def java_opts
29-
@droplet.java_opts
29+
'$JAVA_OPTS'
3030
end
3131

3232
# (see JavaBuildpack::Util::Play::Base#start_script)

0 commit comments

Comments
 (0)