[crac] RFR: 8376959: [CRaC] Turn simengine into shared library [v2]

Timofei Pushkin tpushkin at openjdk.org
Tue Feb 3 14:06:37 UTC 2026


On Tue, 3 Feb 2026 09:37:34 GMT, Radim Vansa <rvansa at openjdk.org> wrote:

>> Right now `simengine` is implemented as an executable, invoked through `libcrexec` that implements the C/R API. Since the programmatic C/R API should be the main interface, any exec API is redundant; let's turn `simengine` into shared (dynamic) library implementing the API on its own.
>> 
>> The `pauseengine` does not need to exist on its own; this can be only an option `pause=true` for `simengine`. The implementation is Linux only (and it is out of scope to fill in a non-Linux implementation - the `pause` option can be just excluded in non-Linux `libsimengine`).
>> 
>> We expect to turn `libcrexec` + `criuengine` into `libcriuengine` in a follow up (not as part of this issue).
>
> Radim Vansa has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Implement static build & other platforms

src/hotspot/share/runtime/crac_engine.cpp line 69:

> 67: }
> 68: 
> 69: static bool find_engine(const char *dll_dir, char *path, size_t path_size, bool *is_library, char *resolved_engine, size_t resolved_engine_size) {

This is becoming so complex... With the planned removal of `crexec` it should become simpler but I wonder if we can also simplify it also by deprecating the ability to use both `nameengine` and `name`: allow only `name` that must map to `nameengine.so`? Can be done in a separate PR.

src/hotspot/share/runtime/crac_engine.cpp line 113:

> 111:   }
> 112: 
> 113:   if (is_pauseengine()) {

Ideally on Mac `pauseengine` should not be treated specially to preserve the old behavior

src/hotspot/share/runtime/crac_engine.cpp line 116:

> 114:     assert(sizeof(SIMENGINE) <= resolved_engine_size, "must be");
> 115:     memcpy(resolved_engine, SIMENGINE, sizeof(SIMENGINE));
> 116:     log_warning(crac)("-XX:CRaCEngine=pause/pauseengine is deprecated; use -XX:CRaCEngine=simengine -XX:CRaCEngineOptions=pause=true");

Let's define an obsoletion/expiration version for this. I suggest 28 for both obsoletion and expiration: this way for LTS releases it will be deprecated in April 2026 and obsoleted+expired in April 2027.

Suggestion:

  assert(JDK_Version::current().compare(JDK_Version::jdk(28)) < 0, "pauseengine handling must be removed as obsolete");
  if (is_pauseengine()) {
    assert(sizeof(SIMENGINE) <= resolved_engine_size, "must be");
    memcpy(resolved_engine, SIMENGINE, sizeof(SIMENGINE));
    log_warning(crac)("Option '-XX:CRaCEngine=pauseengine' was deprecated in version 27 and will be removed in version 28. Use options '-XX:CRaCEngine=simengine -XX:CRaCEngineOptions=pause=true' instead.");

src/hotspot/share/runtime/crac_engine.cpp line 117:

> 115:     memcpy(resolved_engine, SIMENGINE, sizeof(SIMENGINE));
> 116:     log_warning(crac)("-XX:CRaCEngine=pause/pauseengine is deprecated; use -XX:CRaCEngine=simengine -XX:CRaCEngineOptions=pause=true");
> 117:   } else if (static_cast<size_t>(os::snprintf(resolved_engine, resolved_engine_size, "%s", CRaCEngine)) >= resolved_engine_size) {

We could move `path_len = strlen(CRaCEngine)` at the very beginning of this function from under if, use it here for the check and use `memcpy` in case of success instead.

src/hotspot/share/runtime/crac_engine.cpp line 340:

> 338:   if (!find_engine(dll_dir, path, sizeof(path), &is_library,
> 339:     resolved_engine_func + sizeof(CRLIB_API_FUNC), MAX_ENGINE_LENGTH)) {
> 340:     log_error(crac)("Cannot find CRaC engine %s", CRaCEngine);

Suggestion:

  if (!find_engine(dll_dir, path, sizeof(path), &is_library,
      resolved_engine_func + sizeof(CRLIB_API_FUNC), MAX_ENGINE_LENGTH)) {
    log_error(crac)("Cannot find CRaC engine %s", CRaCEngine);

src/java.base/share/native/libcrcommon/crcommon.hpp line 28:

> 26: #define CRCOMMON_HPP
> 27: 
> 28: #include <stdio.h>

Suggestion:

#include <cstdio>

src/java.base/share/native/libcrcommon/crcommon.hpp line 74:

> 72:   void *_image_constraints;
> 73:   void *_image_score;
> 74: };

Since this is not exposed to C, can't this have the actual classes as field types? Also the fields are not private/protected so no underscores should be used.

Actually, since all users of this is also C++ code compiled by the same compiler, isn't it possible to omit the C API layer of `crcommon`?

src/java.base/share/native/libcrexec/environment.hpp line 2:

> 1: /*
> 2:  * Copyright (c) 2025,2026, Azul Systems, Inc. All rights reserved.

Suggestion:

 * Copyright (c) 2025, 2026, Azul Systems, Inc. All rights reserved.

src/java.base/share/native/libsimengine/simengine.cpp line 86:

> 84: 
> 85: static crlib_conf_t* create_simengine() {
> 86:     SimEngine *engine = new(std::nothrow) SimEngine();

Neither `init_conf` nor `SimEngine` constructor report any errors — how are the code and the user supposed to know if something goes wrong there?

-------------

PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758721973
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2759015075
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758659955
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758674949
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758734889
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758838422
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2759025361
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758952911
PR Review Comment: https://git.openjdk.org/crac/pull/289#discussion_r2758813224


More information about the crac-dev mailing list