SI-4331 Fix memory leaks across REPL :reset command
SI-4331 Fix memory leaks across REPL :reset command

Retronym's comment to his fix:

When replacing the classloader, which retains all values created
in the prior REPL lines, we must be careful not to keep around
references to the previous classloader.

We were doing this in two places: the thread context classloader and
in an runtime reflection mirror.

Both of those references to the old classloader would have been
correctness problems, and would likely have meant some degraded
functionality for a post :reset REPL. Furthermore, they served to
retain memory allocated up to the first :reset forever.

I changed handling of the thread context classlaoder to only set and
restore it around execution of code. This avoids leaking the
classloader to whatever thread happend to initialize the REPL.
We actually call the initialization code from within in a background
thread that allows the user to start typing the first command sooner.

I trawled the git logs to understand the history of how and when
we set the context classloader. It was originally added in
7e617ef. A more recent change to
add support for JSR-223 (Scripting) also wrapped this around the
execution 3a30af1. I believe the second commit is the correct
approach, and that it safe to remove the old code.

While this commit makes :reset perform its advertised function,
it doesn't go further to making it a particulary useful command.
Ideally we'd offer a mechanism to transport some data across a :reset
boundary. The user could do something like this manually by stashing
data in a `java.util.Map` hosted in some class in the same classloader
as IMain. They would also have to restrict this to sending "pure data"
rather than instances of data types defined in the REPL session
itself.

I located the leaks with YourKit, and have tested manually by
repeatedly running:

```
 qscala -J-XX:+HeapDumpOnOutOfMemoryError -J-Xmx512M
Welcome to Scala 2.12.0-20151110-111920-44ae563d37 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_51).
Type in expressions for evaluation. Or try :help.

scala> {val b = new Array[Byte](256 * 1024* 1024); () => b}
res0: () => Array[Byte] = $$Lambda$1781/1479140596@4218500f

scala> :reset
Resetting interpreter state.
Forgetting this session history:

{val b = new Array[Byte](256 * 1024* 1024); () => b}

Forgetting all expression results and named terms: $intp

scala> {val b = new Array[Byte](256 * 1024* 1024); () => b}
res0: () => Array[Byte] = $$Lambda$1828/1370495328@6831d8fd

scala> :reset
Resetting interpreter state.
Forgetting this session history:

{val b = new Array[Byte](256 * 1024* 1024); () => b}

scala> {val b = new Array[Byte](256 * 1024* 1024); () => b}
res0: () => Array[Byte] = $$Lambda$1829/79706679@2e140e59

scala> :reset
Resetting interpreter state.
Forgetting this session history:

{val b = new Array[Byte](256 * 1024* 1024); () => b}

scala> {val b = new Array[Byte](256 * 1024* 1024); () => b}
res0: () => Array[Byte] = $$Lambda$1830/1649884294@2418ba04

scala> {val b = new Array[Byte](256 * 1024* 1024); () => b}
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid21760.hprof ...
Heap dump file created [346682068 bytes in 0.870 secs]
java.lang.OutOfMemoryError: Java heap space
  ... 32 elided

scala> :reset
Resetting interpreter state.
Forgetting this session history:

{val b = new Array[Byte](256 * 1024* 1024); () => b}

scala> {val b = new Array[Byte](256 * 1024* 1024); () => b}
res0: 030a7650352a943cde93e977e2244101ececf345@32f5ecc4
```

scala/scala,martijnhoekstra/scala,scala/scala,scala/scala,lrytz/scala,scala/scala,lrytz/scala,martijnhoekstra/scala,martijnhoekstra/scala,lrytz/scala,lrytz/scala,martijnhoekstra/scala,martijnhoekstra/scala,martijnhoekstra/scala,scala/scala,scala/scala,lrytz/scala,lrytz/scala