Reflection warning on setCaretPosition

68 views
Skip to first unread message

Cecil Westerhof

unread,
Feb 27, 2015, 3:56:10 AM2/27/15
to clo...@googlegroups.com
On a editor-pane I use:
    (.setCaretPosition html-table 0)

​And it does what it should do. But when I run:
    lein check

I get:
    Reflection warning, quotes/core.clj:98:42 - call to method setCaretPosition can't be resolved (target class is unknown).

Is that something to worry about?

By the way, I get also some on jdbc and seesaw.​

--
Cecil Westerhof

Gary Verhaegen

unread,
Feb 27, 2015, 5:35:23 AM2/27/15
to clo...@googlegroups.com
It means the Clojure compiler cannot emit the efficient bytecode directly, so it emits bytecode that calls the method reflexively.

This only impacts performance, so if that code is not used much, it is not a problem.

The underlying problem is that jvm bytecode is typed, so ideally the bytecode should be able to say "call method M of type T on object O". Here, the Clojure Compiler cannot infer a type for html-table, so instead the emitted bytecode is more along the lines of "ask object O to give a list of all of its types, then look into each of these types to find if one has a method that matches M in terms of name and number of arguments, and then look at that method's signature and check if the arguments can be cast to the types of the formal parameters; if there is a type with such a method, invoke that method".

This is not 100% technically accurate (in particular, i have no idea what reflection does about the arguments and their types in this case), but it should be roughly correct and you can easily see why that would be much slower.

If you want to remove that warning, you can annotate the html-table variable, but the place where you must do that will depend on a little more context than what you've given here. It is usually done at the level of var declaration or in function argument lists.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Cecil Westerhof

unread,
Feb 27, 2015, 7:07:57 AM2/27/15
to clo...@googlegroups.com
2015-02-27 11:34 GMT+01:00 Gary Verhaegen <gary.ve...@gmail.com>:
It means the Clojure compiler cannot emit the efficient bytecode directly, so it emits bytecode that calls the method reflexively.

This only impacts performance, so if that code is not used much, it is not a problem.

​It is not used much, so it should not be a real problem.
 
 
The underlying problem is that jvm bytecode is typed, so ideally the bytecode should be able to say "call method M of type T on object O". Here, the Clojure Compiler cannot infer a type for html-table, so instead the emitted bytecode is more along the lines of "ask object O to give a list of all of its types, then look into each of these types to find if one has a method that matches M in terms of name and number of arguments, and then look at that method's signature and check if the arguments can be cast to the types of the formal parameters; if there is a type with such a method, invoke that method".

This is not 100% technically accurate (in particular, i have no idea what reflection does about the arguments and their types in this case), but it should be roughly correct and you can easily see why that would be much slower.

If you want to remove that warning, you can annotate the html-table variable, but the place where you must do that will depend on a little more context than what you've given here. It is usually done at the level of var declaration or in function argument lists.

​This is the code:
               (let [html-table (editor-pane
                                 :content-type "text/html"
                                 :text (str html-start
                                            html-records
                                            html-end))
                    ]
                    (.setCaretPosition html-table 0)

So html-table is a JEditorPane. Should Clojure not be able to determine that?


Just to satisfy my curiosity: how can I get rid of the warning?
 
 
On Friday, 27 February 2015, Cecil Westerhof <cldwes...@gmail.com> wrote:
On a editor-pane I use:
    (.setCaretPosition html-table 0)

​And it does what it should do. But when I run:
    lein check

I get:
    Reflection warning, quotes/core.clj:98:42 - call to method setCaretPosition can't be resolved (target class is unknown).

Is that something to worry about?

By the way, I get also some on jdbc and seesaw.​

​Strange enough I only get the warnings on my own code now.
 
--
Cecil Westerhof

Dave Ray

unread,
Feb 27, 2015, 11:30:35 AM2/27/15
to clo...@googlegroups.com
(let [^JEditorPane html-table (editor-pane ...)] ...)  should fix it. Or just set the caret position in the create function:

(editor-pane :caret-position 0)

or use config:

(config! editor-pane :caret-position 0)

Dave


--

Cecil Westerhof

unread,
Feb 27, 2015, 12:18:57 PM2/27/15
to clo...@googlegroups.com
2015-02-27 17:30 GMT+01:00 Dave Ray <dav...@gmail.com>:
(let [^JEditorPane html-table (editor-pane ...)] ...)  should fix it. Or just set the caret position in the create function:

(editor-pane :caret-position 0)

​This one I find the the best option. You only need to do it after the :text option.
 
or use config:

(config! editor-pane :caret-position 0)

 
On Fri, Feb 27, 2015 at 4:07 AM, Cecil Westerhof <cldwes...@gmail.com> wrote:

--
Cecil Westerhof

Cecil Westerhof

unread,
Feb 27, 2015, 12:51:45 PM2/27/15
to clo...@googlegroups.com
2015-02-27 17:30 GMT+01:00 Dave Ray <dav...@gmail.com>:
(let [^JEditorPane html-table (editor-pane ...)] ...)  should fix it. Or just set the caret position in the create function:

​I have removed all my warnings by using: ^JEditorPane, ^JFrame​
 
​, …
But I always like to check deeper. On one of the places I have now:
    ^JLabel (text …

lein check gives no warning, neither does lein compile. And lein run just runs the application. Is that not strange? I say that a JTextField is a JLabel, but the application does not choke on it.​

--
Cecil Westerhof

Andy Fingerhut

unread,
Feb 27, 2015, 1:34:28 PM2/27/15
to clo...@googlegroups.com
If (text ...) is an invocation of a macro, not a function, then that type tag is most likely silently ignored by the Clojure compiler, not hurting anything, but not helping anything, either.

Eastwood [1] can warn you about such useless type tags in your Clojure code, via the :unused-meta-on-macro [2] linter.  Some other incorrect type tags are checked for via the :wrong-tag linter [3].  Not all kinds of Eastwood checks are enabled by default, but those two are.

Andy



--

Fluid Dynamics

unread,
Feb 27, 2015, 5:12:03 PM2/27/15
to clo...@googlegroups.com

If you are only calling methods on the object that exist in those classes' common superclass JComponent, then nothing is likely to go wrong. If you call a JLabel specific method on an object that's actually a JTextField that Clojure merely *thinks* is a JLabel, you'll get a ClassCastException at runtime.
Reply all
Reply to author
Forward
0 new messages