Welcome! Please see the About page for a little more info on how this works.

0 votes
in Errors by

`
Reported by cemer...@snowtide.com, Feb 10, 2009

The jvm has certain implementation limits around the maximum size of
classfiles, literal strings, method length, etc; however, in certain
circumstances, the Clojure compiler can currently emit classfiles that
violate some of those limitations, causing an error later when the
classfile is loaded.

While test coverage would necessarily detect this sort of problem on a
project-by-project basis when one's tests attempted to load a project's
classfiles, it seems like Clojure should do the following to ensure failure
as quickly as possible:

  • throw an exception immediately if, while compiling a lib, it is detected
    that the resulting classfile(s) would violate any classfile implementation
    limits. Ideally, the exception's message would detail what file and on
    which line number the offending form is (e.g. if a method's bytecode would
    be too long). I can imagine that doing this may not be straightforward; a
    reasonable stop-gap would be for the compiler to immediately attempt to
    load the generated classfile in order to ensure up-front failure.

  • emit a warning if any clojure form is read that would, upon being
    compiled, require violating any of the classfile implementation limits; I
    suspect that most people looking to generate classfiles would be doing so
    in a "build" environment (rather than loading some code, tinkering, and
    then using clojure.core/compile), but for those that aren't, I can imagine
    there being a good deal of frustration around seeing that loading and using
    some code successfully would eventually produce unusable classfiles.

I've appended a sample stack trace emitted by java when it attempted to
load a too-long method implementation (which was produced by embedding a
large list literal in a compiled lib).

Exception in thread "main" java.lang.ClassFormatError: Invalid method
Code length 105496 in class file com/foo/MyClass__init

     at java.lang.ClassLoader.defineClass1(Native Method)
     at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
     at  

java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)

     at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
     at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
     at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
     at java.security.AccessController.doPrivileged(Native Method)
     at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:

288)

     at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:

374)

     at java.lang.Class.forName0(Native Method)
     at java.lang.Class.forName(Class.java:247)
     at clojure.lang.RT.loadClassForName(RT.java:1512)
     at clojure.lang.RT.load(RT.java:394)
     at clojure.lang.RT.load(RT.java:374)
     at clojure.core$load__4911$fn__4913.invoke(core.clj:3623)
     at clojure.core$load__4911.doInvoke(core.clj:3622)
     at clojure.lang.RestFn.invoke(RestFn.java:413)
     at clojure.core$load_one__4863.invoke(core.clj:3467)
     at clojure.core$compile__4918$fn__4920.invoke(core.clj:3633)
     at clojure.core$compile__4918.invoke(core.clj:3632)
     at clojure.lang.Var.invoke(Var.java:336)
     at clojure.lang.Compile.main(Compile.java:56) 

`

3 Answers

0 votes
by

Comment made by: importer

Converted from http://www.assembla.com/spaces/clojure/tickets/77

0 votes
by

Comment made by: importer

richhickey said: Updating tickets (#8, #19, #30, #31, #126, #17, #42, #47, #50, #61, #64, #69, #71, #77, #79, #84, #87, #89, #96, #99, #103, #107, #112, #113, #114, #115, #118, #119, #121, #122, #124)

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-77 (reported by cemerick)
...