What version of OR-tools and what language are you using?
Version: or-tools_VisualStudio2019-64bit_v7.6.7691
Language: Java
Which solver are you using
Routing Solver
What operating system and version?
Microsoft Windows [Version 10.0.16299.1932]
What did you do?
I put the method main of the example TspCities.java in an infinite loop; that is, in that example, I changed
public static void main(String[] args) throws Exception { … }
to
public static void _main(String[] args) throws Exception { … }
and added
public static void main(String[] args) throws Exception { while(true) _main(args); }
What did you expect to see
I expected to see no crash in the JVM
What did you see instead?
The JVM crashed after a few seconds with
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa50da9b2a, pid=8984, tid=11524
#
# JRE version: OpenJDK Runtime Environment (14.0.1+7) (build 14.0.1+7)
# Java VM: OpenJDK 64-Bit Server VM (14.0.1+7, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# V [jvm.dll+0x349b2a]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
First we should test using the C++ sample, i'm pretty sure the leak comes from the SWIG wrapper...
Coud you try to call the garbage collector between each iteration ?
e.g.
https://github.com/google/or-tools/blob/45770b833997f827d322e929b1ed4781c4e60d44/examples/tests/TestConstraintSolver.java#L339
note/ AFAIK this test always fails (90%) on windows CI...
If the garbage collector is called after each solution is computed, the JVM does not crash (or, at least, it doesn't crash right after a few seconds). That's what I do now as workaround. For the example above:
public static void main(String[] args) throws Exception {
while (true) { _main(args); System.gc(); }
}
By invoking the garbage collector after a couple of solutions are computed, the JVM takes longer to crash, but it crashes eventually.
public static void main(String[] args) throws Exception {
int i = 0;
while (true) { _main(args); if (++i % 8 == 0) System.gc(); }
}
Another workaround, which is faster, reliable, and works as long as you have enough memory, is storing the reference to all RoutingModel instances created in a static (global) variable:
private static final List<RoutingModel> workaround = new ArrayList<>();
public static void _main(String[] args) throws Exception {
…
RoutingModel routing = new RoutingModel(manager);
workaround.add(routing);
…
}
That is, preventing RoutingModel from bein garbage collected also prevents the JVM from crashing.
I'm having the same issue. Any updates on this?
Unfortunately, I cannot use the workarounds above due to performance issues.
JVM crash log here: https://pastebin.com/1VJCsa1F
EDIT: I also tested on Debian and Alpine and the problem persists.
That is, preventing RoutingModel from bein garbage collected also prevents the JVM from crashing.
No, sooner or later the JVM crashes, no matter which workaround is used.
IIRC java swig wrapper may use globals to store reference to callback, need to check if it can cause a leak or a double free error causing the JVM to crash, I'll try to investigate it...
note: Usually we only instantiate one routing model, solve it, send/display/save result then close the program, i.e. we spawn one program per instance to solve -> need to add some tests and debug how well a server/daemon in Java is stable.
Most helpful comment
If the garbage collector is called after each solution is computed, the JVM does not crash (or, at least, it doesn't crash right after a few seconds). That's what I do now as workaround. For the example above:
By invoking the garbage collector after a couple of solutions are computed, the JVM takes longer to crash, but it crashes eventually.