LoadConfig loads memory calculator configuration from the JRE-specific env var (e.g. JBP_CONFIG_OPEN_JDK_JRE, JBP_CONFIG_SAP_MACHINE_JRE) and falls back to MEMORY_CALCULATOR_* env vars. Must be called at the start of Supply(), before countClasses().
()
| 385 | // to MEMORY_CALCULATOR_* env vars. |
| 386 | // Must be called at the start of Supply(), before countClasses(). |
| 387 | func (m *MemoryCalculator) LoadConfig() { |
| 388 | if m.configLoaded { |
| 389 | return |
| 390 | } |
| 391 | m.configLoaded = true |
| 392 | |
| 393 | // Resolve the env var name for this JRE (e.g. "sapmachine" → "JBP_CONFIG_SAP_MACHINE_JRE") |
| 394 | envVarName := jreNameToDocumentedEnvVar[m.jreName] |
| 395 | if envVarName == "" { |
| 396 | // fallback: auto-generate from jreName |
| 397 | envVarName = fmt.Sprintf("JBP_CONFIG_%s", strings.ToUpper(strings.ReplaceAll(m.jreName, "-", "_"))) |
| 398 | } |
| 399 | |
| 400 | if config := os.Getenv(envVarName); config != "" { |
| 401 | yamlHandler := common.YamlHandler{} |
| 402 | |
| 403 | // Extract raw memory_calculator sub-section to validate its fields separately, |
| 404 | // so unknown top-level keys (e.g. jre:) are silently ignored while typos |
| 405 | // inside memory_calculator: are warned about. |
| 406 | rawCfg := struct { |
| 407 | MC interface{} `yaml:"memory_calculator"` |
| 408 | }{} |
| 409 | if err := yamlHandler.Unmarshal([]byte(config), &rawCfg); err == nil && rawCfg.MC != nil { |
| 410 | if mcBytes, err := yamlHandler.Marshal(rawCfg.MC); err == nil { |
| 411 | if err := yamlHandler.ValidateFields(mcBytes, &memoryCalculatorConfig{}); err != nil { |
| 412 | m.ctx.Log.Warning("Unknown fields in %s memory_calculator: %s", envVarName, err.Error()) |
| 413 | } |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | cfg := openJDKJREConfig{} |
| 418 | if err := yamlHandler.Unmarshal([]byte(config), &cfg); err != nil { |
| 419 | m.ctx.Log.Warning("Failed to parse %s: %s", envVarName, err.Error()) |
| 420 | } else { |
| 421 | mc := cfg.MemoryCalculator |
| 422 | if mc.StackThreads > 0 { |
| 423 | m.stackThreads = mc.StackThreads |
| 424 | m.stackThreadsUserSet = true |
| 425 | } |
| 426 | if mc.ClassCount > 0 { |
| 427 | m.classCount = mc.ClassCount |
| 428 | m.classCountUserSet = true |
| 429 | } |
| 430 | if mc.Headroom > 0 { |
| 431 | m.headroom = mc.Headroom |
| 432 | m.headroomUserSet = true |
| 433 | } |
| 434 | } |
| 435 | } |
| 436 | |
| 437 | if val := os.Getenv("MEMORY_CALCULATOR_STACK_THREADS"); val != "" { |
| 438 | if threads, err := strconv.Atoi(val); err == nil { |
| 439 | m.stackThreads = threads |
| 440 | m.stackThreadsUserSet = true |
| 441 | } |
| 442 | } |
| 443 | |
| 444 | if val := os.Getenv("MEMORY_CALCULATOR_HEADROOM"); val != "" { |
no test coverage detected