Java OutOfMemoryError during build task :jar

Enonic version: 7.12.2
OS: Linux (Docker) & Windows

Hi,

We’re working on moving our current XP 7.12 project into a React4XP one, still in 7.12.
One of the critical functionalities is exporting HTML to PDF in the backend, specially due an archiving system (editor publishes something, the PDF is created and sent to this system’s API). Still today, we rely on an old lib to export the scripts: openxp/lib-html-exporter. After upgrading to XP 7.12, nothing seemed to change.

After moving into React4XP context, the build process started throwing heap space exceptions. Since we also had a bit of restructuring done, we handpicked out a few pieces of the building process, until we tracked the error to this lib. Removing it from build.gradle does the trick.
We tried locally building the lib in a 7.12 sandbox and including it into build.gradle through flatDir, but with no success.

The screenshots are when using the online repo:

A piece of the process log (due character limit):

> @enonic/[email protected] tsup:client
> npx tsup --config tsup.config.client.ts

CLI Building entry: {"client":"src/client.ts"}
CLI Using tsconfig: tsconfig.client.json
CLI tsup v7.2.0
CLI Using tsup config: /enonic-xp/source/node_modules/@enonic/react4xp/tsup.config.client.ts
CLI Target: es2015
IIFE Build start
IIFE ../../../build/resources/main/r4xAssets/client.manifest.json      46.00 B
IIFE ../../../build/resources/main/r4xAssets/client-K3FFXGN2.global.js 12.25 KB
IIFE ⚡ Build success in 51ms

> @enonic/[email protected] webpack:components
> cross-env TS_NODE_PROJECT="tsconfig.browserAndGraalJS.json" webpack --config dist/webpack.config.components.js

EXTERNALS:
{
  react: 'React',
  'react-dom': 'ReactDOM',
  'react-dom/server': 'ReactDOMServer'
}
R4X_DIR_PATH_ABSOLUTE_PROJECT: /enonic-xp/source
filePathAbsoluteWebpackOverride: /enonic-xp/source/webpack.config.react4xp.js


---
chunkDirsStringArray:
[]
--> chunkDirs:
[]


---
entryDirsStringArray:
[]
--> entryDirs:
[]
---



---entrySets:
[
  {
    sourcePath: '/enonic-xp/source/src/main/resources/site',
    sourceExtensions: [
      'jsx',
      'tsx'
    ],
    targetSubDir: 'site'
  }
]
Entries from subfolder - entry set:
{
  sourcePath: '/enonic-xp/source/src/main/resources/site',
  sourceExtensions: [
    'jsx',
    'tsx'
  ],
  targetSubDir: 'site'
}
        Entry: site/parts/color/color -> /enonic-xp/source/src/main/resources/site/parts/color/color.tsx
React4xp entries (a.k.a jsxPath) listed in: /enonic-xp/source/build/resources/main/r4xAssets/entries.json

react4xp-build-components - entries:
{
  'site/parts/color/color': '/enonic-xp/source/src/main/resources/site/parts/color/color.tsx'
}
makeExclusionsRegexpString currentDir: /enonic-xp/source/src/main/resources/react4xp
makeExclusionsRegexpString otherDirs:
[]
makeExclusionsRegexpString returnValue:

-------------------- react4xp-build-components - webpack config output:
{
  context: '/enonic-xp/source',
  devtool: 'source-map',
  entry: {
    'site/parts/color/color': '/enonic-xp/source/src/main/resources/site/parts/color/color.tsx'
  },
  externals: {
    react: 'React',
    'react-dom': 'ReactDOM',
    'react-dom/server': 'ReactDOMServer'
  },
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.((j|t)sx?|es6?)$/,
        exclude: [
          /node_modules[\\/]core-js/,
          /node_modules[\\/]webpack[\\/]buildin/
        ],
        use: [
          {
            loader: 'swc-loader',
            options: {
              jsc: {
                parser: {
                  dynamicImport: false,
                  jsx: true,
                  syntax: 'typescript',
                  tsx: true
                }
              },
              minify: true,
              sourceMaps: true
            }
          }
        ]
      }
    ]
  },
  optimization: {
    chunkIds: 'deterministic',
    innerGraph: true,
    mangleWasmImports: false,
    minimize: true,
    mergeDuplicateChunks: true,
    moduleIds: 'deterministic',
    removeAvailableModules: true,
    removeEmptyChunks: true,
    runtimeChunk: 'single',
    sideEffects: true,
    splitChunks: {
      chunks: 'all',
      name: false,
      cacheGroups: {
        vendors: {
          enforce: true,
          filename: '[name].[contenthash].js',
          name: 'vendors',
          priority: 100,
          test: /[\\/]node_modules[\\/](?!@enonic[\\/]react-components)./,
          usedExports: true
        },
        templates: {
          enforce: true,
          filename: '[name].[contenthash].js',
          name: 'templates',
          priority: 99,
          test: /[\\/]node_modules[\\/]@enonic[\\/]react-components/,
          usedExports: true
        },
        react4xp: {
          enforce: true,
          filename: '[name].[contenthash].js',
          name: 'react4xp',
          priority: 1,
          test: /\/enonic-xp\/source\/src\/main\/resources\/react4xp[\\/]/,
          usedExports: true
        }
      }
    },
    usedExports: true
  },
  output: {
    path: '/enonic-xp/source/build/resources/main/r4xAssets',
    pathinfo: false,
    filename: '[name].[contenthash].js',
    library: {
      name: [
        'HelsedirektoratetReact4xp',
        '[name]'
      ],
      type: 'global'
    },
    globalObject: 'globalThis',
    environment: {
      arrowFunction: false,
      bigIntLiteral: false,
      const: false,
      destructuring: false,
      dynamicImport: false,
      forOf: false,
      module: false
    }
  },
  plugins: [
    CaseSensitivePathsPlugin {
      options: {},
      logger: {
        log: function () { [native code] },
        warn: function () { [native code] },
        dir: function () { [native code] },
        time: function () { [native code] },
        timeEnd: function () { [native code] },
        timeLog: function () { [native code] },
        trace: function () { [native code] },
        assert: function () { [native code] },
        clear: function () { [native code] },
        count: function () { [native code] },
        countReset: function () { [native code] },
        group: function () { [native code] },
        groupEnd: function () { [native code] },
        table: function () { [native code] },
        debug: function () { [native code] },
        info: function () { [native code] },
        dirxml: function () { [native code] },
        error: function () { [native code] },
        groupCollapsed: function () { [native code] },
        Console: Function Console,
        profile: function profile() { [native code] },
        profileEnd: function profileEnd() { [native code] },
        timeStamp: function timeStamp() { [native code] },
        context: function context() { [native code] }
      },
      pathCache: Map {},
      fsOperations: 0,
      primed: false
    },
    StatsWriterPlugin {
      opts: {
        filename: 'stats.components.json',
        fields: null,
        stats: {
          assets: true,
          entrypoints: true,
          errors: true,
          warnings: true,
          builtAt: false,
          cached: false,
          cachedAssets: false,
          children: false,
          chunks: false,
          chunkGroups: false,
          chunkModules: false,
          chunkOrigins: false,
          depth: false,
          env: false,
          errorDetails: false,
          hash: false,
          modules: false,
          moduleTrace: false,
          performance: false,
          providedExports: false,
          publicPath: false,
          reasons: false,
          source: false,
          timings: false,
          usedExports: false,
          version: false
        },
        transform: (data) => JSON.stringify(data, null, INDENT),
        emit: true
      }
    }
  ],
  resolve: {
    extensions: [
      '.tsx',
      '.jsx',
      '.ts',
      '.es6',
      '.es',
      '.js',
      '.json'
    ],
    modules: [
      '/enonic-xp/source/node_modules',
      '/enonic-xp/source/node_modules/@enonic/react4xp/node_modules'
    ],
    roots: [
      '/enonic-xp/source/src/main/resources'
    ],
    symlinks: true
  },
  stats: {
    colors: true,
    hash: false,
    logging: 'log',
    modules: false,
    moduleTrace: false,
    timings: false,
    version: false
  }
}
asset runtime.223729ef8e556bab20fb.js 1.48 KiB [emitted] [immutable] [minimized] (name: runtime) 1 related asset
asset stats.components.json 1.16 KiB [emitted]
asset site/parts/color/color.e6a6d4c33eb6d9c0db7f.js 648 bytes [emitted] [immutable] [minimized] (name: site/parts/color/color) 1 related asset
Entrypoint site/parts/color/color 2.11 KiB (8.96 KiB) = runtime.223729ef8e556bab20fb.js 1.48 KiB site/parts/color/color.e6a6d4c33eb6d9c0db7f.js 648 bytes 2 auxiliary assets

LOG from webpack.Compilation
    1 modules hashed, 0 from cache (0.5 variants per module in average)
    100% code generated (1 generated, 0 from cache)
    100% code generated (6 generated, 0 from cache)
+ 24 hidden lines

LOG from webpack.FlagDependencyExportsPlugin
    100% of exports of modules have been determined (0 no declared exports, 1 not cached, 1 flagged uncacheable, 0 from cache, 0 from mem cache, 0 additional calculations due to dependencies)
+ 3 hidden lines

LOG from webpack.buildChunkGraph
    4 queue items processed (2 blocks)
    0 chunk groups connected
    0 chunk groups processed for merging (0 module sets, 0 forked, 0 + 0 modules forked, 0 + 0 modules merged into fork, 0 resulting modules)
    0 chunk group info updated (0 already connected chunk groups reconnected)
+ 5 hidden lines

LOG from webpack.FileSystemInfo
    1 new snapshots created
    0% root snapshot uncached (0 / 0)
    0% children snapshot uncached (0 / 0)
    0 entries tested
    File info in cache: 1 timestamps 1 hashes 1 timestamp hash combinations
    File timestamp hash combination snapshot optimization: 0% (0/1) entries shared via 0 shared snapshots (0 times referenced)
    Directory info in cache: 0 timestamps 0 hashes 0 timestamp hash combinations
    Managed items info in cache: 0 items

webpack compiled successfully

> @enonic/[email protected] tsup:executor
> npx tsup --config tsup.config.executor.ts

CLI Building entry: {"executor":"src/executor.ts"}
CLI Using tsconfig: tsconfig.executor.json
CLI tsup v7.2.0
CLI Using tsup config: /enonic-xp/source/node_modules/@enonic/react4xp/tsup.config.executor.ts
CLI Target: es2015
CJS Build start
CJS ../../../build/resources/main/r4xAssets/executor.manifest.json 43.00 B
CJS ../../../build/resources/main/r4xAssets/executor-GXIEMGRZ.js   949.00 B
CJS ⚡ Build success in 41ms

> @enonic/[email protected] webpack:globals
> cross-env TS_NODE_PROJECT="tsconfig.browserAndGraalJS.json" webpack --config dist/webpack.config.globals.js

DIR_PATH_ABSOLUTE_BUILD_ASSETS_R4X (string): "/enonic-xp/source/build/resources/main/r4xAssets"
GLOBALS:
{
  react: 'React',
  'react-dom': 'ReactDOM',
  'react-dom/server': 'ReactDOMServer'
}
GLOBALS:
{
  react: 'React',
  'react-dom': 'ReactDOM',
  'react-dom/server': 'ReactDOMServer'
}
<i> [FileManagerPlugin] created directory. /enonic-xp/source/build/resources/main/r4xAssets
File successfully created - /enonic-xp/source/build/resources/main/r4xAssets/globals.json
asset globals.4427e5cbb5e9bb528fc6.js 204 KiB [emitted] [immutable] [minimized] (name: globals) 2 related assets

LOG from webpack.DefinePlugin
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""
    Replaced "process.env.NODE_ENV" with ""production""

LOG from webpack.Compilation
    10 modules hashed, 0 from cache (1 variants per module in average)
    100% code generated (10 generated, 0 from cache)
+ 24 hidden lines

LOG from webpack.FlagDependencyExportsPlugin
    100% of exports of modules have been determined (0 no declared exports, 10 not cached, 0 flagged uncacheable, 0 from cache, 0 from mem cache, 3 additional calculations due to dependencies)
+ 3 hidden lines

LOG from webpack.buildChunkGraph
    20 queue items processed (10 blocks)
    0 chunk groups connected
    0 chunk groups processed for merging (0 module sets, 0 forked, 0 + 0 modules forked, 0 + 0 modules merged into fork, 0 resulting modules)
    0 chunk group info updated (0 already connected chunk groups reconnected)
+ 5 hidden lines

LOG from webpack.FileSystemInfo
    10 new snapshots created
    0% root snapshot uncached (0 / 0)
    0% children snapshot uncached (0 / 0)
    0 entries tested
    File info in cache: 0 timestamps 0 hashes 0 timestamp hash combinations
    Directory info in cache: 0 timestamps 0 hashes 0 timestamp hash combinations
    Managed items info in cache: 4 items
    Managed items snapshot optimization: 0% (0/10) entries shared via 0 shared snapshots (0 times referenced)
    Managed files snapshot optimization: 0% (0/20) entries shared via 0 shared snapshots (0 times referenced)

webpack compiled successfully

> @enonic/[email protected] webpack:nashornPolyfills
> cross-env TS_NODE_PROJECT="tsconfig.browserAndGraalJS.json" webpack --config dist/webpack.config.nashornPolyfills.js

/enonic-xp/source/src/main/resources/react4xpNashornPolyfills.es6 not found, which is fine :)
LOG from webpack.CompilationG [55s]
    0 modules hashed, 0 from cache (NaN variants per module in average)
+ 22 hidden lines

LOG from webpack.FlagDependencyExportsPlugin
    NaN% of exports of modules have been determined (0 no declared exports, 0 not cached, 0 flagged uncacheable, 0 from cache, 0 from mem cache, 0 additional calculations due to dependencies)
+ 3 hidden lines

LOG from webpack.buildChunkGraph
    0 queue items processed (0 blocks)
    0 chunk groups connected
    0 chunk groups processed for merging (0 module sets, 0 forked, 0 + 0 modules forked, 0 + 0 modules merged into fork, 0 resulting modules)
    0 chunk group info updated (0 already connected chunk groups reconnected)
+ 3 hidden lines

LOG from webpack.FileSystemInfo
    0 new snapshots created
    0% root snapshot uncached (0 / 0)
    0% children snapshot uncached (0 / 0)
    0 entries tested
    File info in cache: 0 timestamps 0 hashes 0 timestamp hash combinations
    Directory info in cache: 0 timestamps 0 hashes 0 timestamp hash combinations
    Managed items info in cache: 0 items

webpack compiled successfully
:react4xp (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 24.288 secs.
:jar (Thread[Execution worker for ':' Thread 2,5,main]) started.

> Task :jar
Caching disabled for task ':jar' because:
  Build cache is disabled
Task ':jar' is not up-to-date because:
  Task has failed previously.

Exception in thread "Daemon client event forwarder" java.lang.OutOfMemoryError: Java heap space

> Task :jar FAILED
:jar (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 45.188 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':jar'.
> Java heap space

* Try:
> Run with --debug option to get more log output.
> Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':jar'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:145)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:282)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:143)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:131)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:402)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:389)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:382)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:368)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:61)
Caused by: java.lang.OutOfMemoryError: Java heap space
        at aQute.bnd.signatures.Signatures.erasedBinaryReferences(Signatures.java:73)
        at aQute.bnd.signatures.FieldSignature.erasedBinaryReferences(FieldSignature.java:25)
        at aQute.bnd.osgi.Clazz.referTo(Clazz.java:1631)
        at aQute.bnd.osgi.Clazz.parseClassFileData(Clazz.java:842)
        at aQute.bnd.osgi.Clazz.parseClassFileData(Clazz.java:784)
        at aQute.bnd.osgi.Clazz.parseClassFileWithCollector(Clazz.java:772)
        at aQute.bnd.osgi.Clazz.parseClassFile(Clazz.java:762)
        at aQute.bnd.osgi.Analyzer.analyzeJar(Analyzer.java:2673)
        at aQute.bnd.osgi.Analyzer.analyzeBundleClasspath(Analyzer.java:2584)
        at aQute.bnd.osgi.Analyzer.analyzeContent(Analyzer.java:442)
        at aQute.bnd.osgi.Analyzer.analyze(Analyzer.java:204)
        at aQute.bnd.osgi.Builder.analyze(Builder.java:445)
        at aQute.bnd.osgi.Analyzer.calcManifest(Analyzer.java:1035)
        at aQute.bnd.osgi.Builder.build(Builder.java:128)
        at aQute.bnd.gradle.BundleTaskExtension$BuildAction.execute(BundleTaskExtension.java:538)
        at aQute.bnd.gradle.BundleTaskExtension$BuildAction.execute(BundleTaskExtension.java:399)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:770)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:743)
        at org.gradle.api.internal.tasks.execution.TaskExecution$2.run(TaskExecution.java:239)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:224)


* Get more help at https://help.gradle.org

BUILD FAILED in 1m 42s
15 actionable tasks: 5 executed, 10 up-to-date
Some of the file system contents retained in the virtual file system are on file systems that Gradle doesn't support watching. The relevant state was discarded to ensure changes to these locations are properly detected. You can override this by explicitly enabling file system watching.
make: *** [Makefile:33: build] Erro 1

This has somehow flown over our heads… Did you figure it out or do you still need help?

Unfortunately I hadn’t. I noticed that in other projects (without React4XP), including webpack ones, it builds successfully, so I moved the lib to an util-app (even though it forces an extra http request in the server). This got the PDF system running.

We moved this solution to Production. Not the best, but at least it works.