Clojure

Avoid initializing Class when using Class as a value

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Problem:
When an imported class is used as a value, the emitted bytecode uses RT.classForName to obtain the Class object, causing the class to be loaded and static initializers to be executed. This is different from when Java calls static initializers and makes it more difficult to use clojure with code that depend on the Java semantics.

Motivation
Some code has static initializers that can only execute in a certain environment. A prime example is JavaFX, where many JavaFX classes require the JavaFX platform to be started before any static initializers can run.

Consider this code:

example.clj
(import 'javafx.scene.control.Cell)

(defn f [] Cell)

It currently can't be compiled and executed (for example with "clj example.clj" using clojure-1.9.0beta2) failing with a CompilerException java.lang.ExceptionInInitializerError, with the root cause "Toolkit not initialized". This use of Cell as the return value of f causes the class to be loaded and initialised.

Approach
Modify ObjExpr.emitValue to emit a call to RT.classForNameNonLoading instead of RT.classForName when the value being emitted is a Class.

Patch
https://dev.clojure.org/jira/secure/attachment/17426/CLJ-2250-avoid-initializing-class-when-used-as-value.patch

Prior art
The import form previously was changed to similarly not load the class (CLJ-1315) and CLJ-1743 attempts to address similar issues where Clojure differs from the Java semantics.

Activity

Hide
Ragnar Dahlen added a comment -

Added patch.

Show
Ragnar Dahlen added a comment - Added patch.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated: