resolve fails in compiled code, but works in source-code

Description

In clojure-clr 1.5 resolve returns nil in compiled code only.
clojure 1.6. and 1.7 throw an exception in function test-existence3, while resolve works fine in the first two functions.

The output when running from binary/compiled under 1.5 (clr1.5-test-bin.bat) is:

------------------------------------- try to run from binary file
About to load the file
0. Check loading via a resolve: log4net.Config.XmlConfigurator
1. (test-existence1) Double-check log4net via a resolve: log4net.ILog
2. Double-check log4net via a resolve: nil AND nil

NOTE: the log4net-items are only resolved when running from sources. When running from compiled/binary code this call fails when a function from the log4net dll is used within this function body.

3. Double-check log4net via a resolve: nil AND nil

NOTE: Moving this code to a sub-function does NOT solve the issue.

READY
Press any key to continue . . .
--------------------------------------------
this bug is a very nasty one as it only surfaces when you are trying to deploy as compiled code, so the issue is usually detected long after writing the code that contains the issue.

Cees.

Environment

clojure-clr 1.5, 1.6 and 1.7

Activity

Show:
David Miller
November 27, 2015, 6:18 PM

I'm getting the same behavior compiled and interpreted under 1.8.
The resolve is happening properly in both cases.

I was having a problem with loading log4net.dll. I put this dll in a known location and modified your call to assembly-load-file to be assembly-load-from so I could use a relative path.
Worked fine interpreted.
However, it failed compiled because the compiled logger.clj.dll file explicitly references the log4net assembly and tries to load it via the usual CLR assembly loading procedure. It cannot find the file to load (even though I already loaded it, it is trying to load it again) and blows up.
When I move a copy of log4net into the clojure executable directory, it succeeds.

So, I cannot reproduce the behavior you have. Everything resolves.

from compiled:

Clojure 1.8.0-master-SNAPSHOT
user=> (require 'compileBug.logger)
0. Check loading via a resolve: log4net.Config.XmlConfigurator
1. (test-existence1) Double-check log4net via a resolve: log4net.ILog
2. Double-check log4net via a resolve: log4net.ILog AND log4net.Config.XmlConfigurator

NOTE: the log4net-items are only resolved when running from sources. When running from compiled/binary code this call fails when a function from the log4net dll is used within this function body.

3. Double-check log4net via a resolve: log4net.ILog AND log4net.Config.XmlConfigurator

NOTE: Moving this code to a sub-function does NOT solve the issue.

nil
user=>

Not sure how to proceed at this point.

David Miller
November 27, 2015, 5:31 PM

The reason for introducing the TypeNotFoundException was to emulate the JVM behavior, which does throw rather than returning null.
The 1.5 behavior did not match the JVM.
I do not remember the reason I changed it to match the JVM behavior. It was either to match test behavior or at the request of someone who had a problem with the 1.5 behavior.

That being said, differences between compiled and REPL behavior is not good. That still needs investigation.
-David

Cees van Kemenade
September 28, 2015, 9:21 PM

I observed that the clojure.lang.TypeNotFoundException does not exist clr-1.5, so it seems that a new exception-type was introduced in clr-1.6. Possible the code of resolve still tries to catch the old clr-1.5 exception and therefore does not catch the new TypeNotFoundException.

Cees van Kemenade
September 28, 2015, 8:37 PM

When running in the repl (interactive mode) I also notice an important difference between clr-1.5 on the one hand and clr1.6. and 1.7 on the other hand.

When using resolve in 1.5 and the assembly/library containing the symbol is not loaded we get a nil value. In clr1.6 and clr1.7 we get a clojure.lang.TypeNotFoundException.
The behavior of clr-1.5. is the desired/correct behavior. The behavior of clr-1.6 and clr-1.7 is odd in my opinion.

When using ns-resolve we get:
user=> (ns-resolve 'log4net.Config 'XmlConfigurator)
Exception No namespace: log4net.Config found clojure/core$the_ns__3933.invoke (:0)

I think this is related to the bug above, but it surfaces in a different manner.

Cees

Not Reproducible

Assignee

David Miller

Reporter

Cees van Kemenade