0
votes

Works fine in Corda 3.3 but fails in Corda 4.0

Node gets up properly and then when I call first very simple flow - this error happens.

I tried to run node with 2048 heap space but no success.

Stacktrace:

java.lang.RuntimeException: java.util.concurrent.ExecutionException: Exception while scanning at io.github.classgraph.ClassGraph.scan(ClassGraph.java:1153) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.ClassGraph.scan(ClassGraph.java:1173) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.ClassGraph.scan(ClassGraph.java:1185) ~[classgraph-4.6.12.jar:4.6.12] at net.corda.core.internal.ClassGraphUtilsKt.pooledScan(ClassGraphUtils.kt:18) ~[corda-core-4.0.jar:?] at net.corda.core.internal.ClassLoadingUtilsKt.createInstancesOfClassesImplementing(ClassLoadingUtils.kt:22) ~[corda-core-4.0.jar:?] at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder$withAttachmentsClassloaderContext$serializationContext$1.apply(AttachmentsClassLoader.kt:316) ~[corda-core-4.0.jar:?] at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder$withAttachmentsClassloaderContext$serializationContext$1.apply(AttachmentsClassLoader.kt:293) ~[corda-core-4.0.jar:?] at java.util.HashMap.computeIfAbsent(HashMap.java:1127) ~[?:1.8.0_191] at java.util.Collections$SynchronizedMap.computeIfAbsent(Collections.java:2672) ~[?:1.8.0_191] at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder.withAttachmentsClassloaderContext(AttachmentsClassLoader.kt:313) ~[corda-core-4.0.jar:?] at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder.withAttachmentsClassloaderContext$default(AttachmentsClassLoader.kt:310) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.LedgerTransaction.internalPrepareVerify$core(LedgerTransaction.kt:135) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.LedgerTransaction.verify(LedgerTransaction.kt:125) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.TransactionBuilder.addMissingDependency(TransactionBuilder.kt:173) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.TransactionBuilder.toWireTransactionWithContext$core(TransactionBuilder.kt:160) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.TransactionBuilder.toWireTransactionWithContext$core$default(TransactionBuilder.kt:128) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.TransactionBuilder.toWireTransaction(TransactionBuilder.kt:125) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.TransactionBuilder.toLedgerTransaction(TransactionBuilder.kt:451) ~[corda-core-4.0.jar:?] at net.corda.core.transactions.TransactionBuilder.verify(TransactionBuilder.kt:459) ~[corda-core-4.0.jar:?] at com.insettle.core.corda.flows.abstractions.AbstractInitiatingFlow.call(AbstractInitiatingFlow.kt:60) ~[?:?] at com.insettle.core.corda.flows.abstractions.AbstractInitiatingFlow.call(AbstractInitiatingFlow.kt:12) ~[?:?] at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:228) ~[corda-node-4.0.jar:?] at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45) ~[corda-node-4.0.jar:?] at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10] at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10] at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10] at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_191] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_191] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_191] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_191] at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.0.jar:?] Caused by: java.util.concurrent.ExecutionException: Exception while scanning at io.github.classgraph.Scanner.call(Scanner.java:716) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.Scanner.call(Scanner.java:63) ~[classgraph-4.6.12.jar:4.6.12] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_191] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191] Caused by: java.lang.OutOfMemoryError: Java heap space at io.github.classgraph.ClassInfo.(ClassInfo.java:154) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.ClassInfo.(ClassInfo.java:169) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.ClassInfo.addScannedClass(ClassInfo.java:489) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.ClassInfoUnlinked.link(ClassInfoUnlinked.java:168) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.Scanner.call(Scanner.java:649) ~[classgraph-4.6.12.jar:4.6.12] at io.github.classgraph.Scanner.call(Scanner.java:63) ~[classgraph-4.6.12.jar:4.6.12] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_191] at java.lang.Thread.run(Thread.java:748) ~[?:1.8.0_191]

2

2 Answers

1
votes

This issue is probably related to the custom whitelist serialization scanning code.

We need to raise max heap size of nodes to 1GB. See following link for details -
https://r3-cev.atlassian.net/browse/CORDA-2436

Also refer - https://r3-cev.atlassian.net/browse/CORDA-2437?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel

0
votes

The stack trace shows:

at io.github.classgraph.ClassGraph.scan(ClassGraph.java:1185) ~[classgraph-4.6.12.jar:4.6.12]
at net.corda.core.internal.ClassGraphUtilsKt.pooledScan(ClassGraphUtils.kt:18) ~[corda-core-4.0.jar:?]
at net.corda.core.internal.ClassLoadingUtilsKt.createInstancesOfClassesImplementing(ClassLoadingUtils.kt:22) ~[corda-core-4.0.jar:?]

In other words it looks like every time createInstancesOfClassesImplementing is called, a new ClassGraph scan is initiated. Assuming that this method is called many times, then not only is that extremely inefficient, but scanning the entire classpath for each new scan could result in a huge amount of memory overhead, if a reference to the ScanResult is held for each new scan.

The stacktrace shows two separate scans going on at the same time too, so you are probably initiating the scan from more than one thread at a time.

The right way to solve this is to scan the classpath just once on initialization, then reuse the ScanResult in ClassLoadingUtilsKt, rather than re-scanning to generate a new ScanResult each time.