java

Jim Newton 2020-10-28T15:07:37.012800Z

Hi everyone. I have some questions about objects which respond true to the clojure class? function. First of all what is the correct word to use to describe the set of objects for which class? returns true? I want to call them "classes" but sometimes people complain that interfaces are not classes.

2020-10-28T15:10:37.013800Z

The Java Virtual Machine specification (separate from the Java language specification, which specifies Java source code) uses the names classes and interfaces, e.g. you can find occurrences of both in the table of contents here: https://docs.oracle.com/javase/specs/jvms/se8/html/

2020-10-28T15:12:01.014500Z

The Java documentation for the class java.lang.Class says near the beginning: "Instances of the class `Class` represent classes and interfaces in a running Java application." -- https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html

Jim Newton 2020-10-28T15:12:50.015800Z

interesing. so the word "Class" with a capital C includes classes and interfaces ?

alexmiller 2020-10-28T15:13:01.016400Z

class is used both as a generic name (including interfaces) and as a specific thing (concrete classes distinct from interfaces) depending on context, but yes Class includes both

2020-10-28T15:13:04.016500Z

And the phrase "class and interface" and "class or interface" is sprinkled all over that last documentation page I linked.

Jim Newton 2020-10-28T15:13:06.016700Z

the set of objects of class java.lang.Class ?

alexmiller 2020-10-28T15:14:19.018Z

there are also arrays, which are objects but somewhat outside typical classes, and primitives

Jim Newton 2020-10-28T15:14:40.018400Z

it's hard to talk about the world with a limited number of words which different people attach different semantics to.

alexmiller 2020-10-28T15:15:07.018600Z

ain't that the truth

2020-10-28T15:16:03.019300Z

Hence the use of short phrases and definitions of terms within a document that needs to make precise distinctions that are not often made casually.

Jim Newton 2020-10-28T15:19:02.020800Z

OK, 2nd question. Can someone give me an example of two interfaces (which I can reference by name in clojure such as java.lang.Comparable or <http://java.io|java.io>.Serializable) which are incompatible in the sense that they both have a member with the same name and the same parameter types?

Jim Newton 2020-10-28T15:21:27.022200Z

i.e. two interfaces which are guaranteed never to be simultaneously in the ancestors list of any one Class (with a capital C)

2020-10-28T15:22:35.023400Z

If no one knows, one way to attempt to answer the question is to run some code that scans the JVM's internal state to try to find all current instances of java.lang.Class, keeps only the ones that represent interfaces, and write some code that collects together all of their method names and signatures, looking for similar ones.

2020-10-28T15:24:00.024900Z

I have some Clojure code somewhere I can probably link to that uses a library written by someone else to look for all (or at least most) instances of java.lang.Class in a running JVM. I haven't written code to do the latter part, but it should be straightforward to write given a collection of instances of java.lang.Class

Jim Newton 2020-10-28T15:25:44.026Z

I tried to find the descendants of Object, but that doesn't work. If it did I could find all descendants, then fall all their ancestors. Since interfaces won't be descendants, but gathering all the ancestors would find a huge number of interfaces.

Jim Newton 2020-10-28T15:25:48.026200Z

😞

Jim Newton 2020-10-28T15:27:15.027300Z

@andy.fingerhut indeed, given a collection of a large number of instances of java.lang.Class, yes I would have a good chance of finding such interfaces.

2020-10-28T15:29:18.029Z

The JVM set of classes and interfaces is by design very dynamic, and they can be loaded/created by a myriad of different ClassLoader objects, and there are security mechanisms to try to hide the existence of some from different "places" in the system, so there are varying degrees of completeness you can achieve with such a list, depending on how you do it.

2020-10-28T15:30:00.029400Z

It might be an hour or three before I find the code I wrote (away from that laptop right now)

alexmiller 2020-10-28T15:30:15.029700Z

you could skim the javadoc index

alexmiller 2020-10-28T15:32:29.030500Z

like abort() is a "method in interface" for many interfaces, probably not all the same hierarchy

alexmiller 2020-10-28T15:33:16.031Z

http://java.net.http.WebSocket and javax.security.auth.spi.LoginModule

alexmiller 2020-10-28T15:35:30.031300Z

accept(<foo>)

alexmiller 2020-10-28T15:37:02.031500Z

add(<foo>)

alexmiller 2020-10-28T15:37:13.031800Z

probably pick any common verb :)

Jim Newton 2020-10-28T15:37:49.032200Z

http://java.net.http.WebSocket seems to be both :abstract and also :interface

alexmiller 2020-10-28T15:37:59.032400Z

all interfaces are abstract

Jim Newton 2020-10-28T15:38:13.032700Z

ah ha, but not all abstracts are interfaces?

alexmiller 2020-10-28T15:38:18.032900Z

correct

Jim Newton 2020-10-28T15:38:28.033300Z

promise?

alexmiller 2020-10-28T15:38:44.033700Z

abstract classes can't be instantiated

alexmiller 2020-10-28T15:39:12.034200Z

they have to be subclassed and made non-abstract (usually by overriding abstract methods)

Jim Newton 2020-10-28T16:11:35.035Z

what does it mean if a Class is not :abstract, and not :interface, and not :final ?

Jim Newton 2020-10-28T16:11:56.035300Z

does it work the same as abstract but can be instantiated?

2020-10-28T16:13:27.036300Z

If it is none of those, that is probably the most common kind of class that people learn to create in Java first. It is a class, not an interface. It is not declared abstract, so you can use new to construct instances of that class. It is not final, so you can define subclasses of it if you wish.

2020-10-28T16:14:44.037500Z

interface -> it is a Java interface (implies abstract, and I believe never final), abstract -> cannot construct instances of it. final -> cannot declare subclasses of it

Jim Newton 2020-10-28T16:14:47.037600Z

ahhh, so these are common ?

Jim Newton 2020-10-28T16:14:52.037800Z

not exotic?

2020-10-28T16:15:03.038100Z

Having none of those three flags present is common

Jim Newton 2020-10-28T16:15:34.038800Z

do we have examples of those in clojure other than Object ?

Jim Newton 2020-10-28T16:15:57.039400Z

Object is the one that I have seen. and I've made a special case of it. but if this is common, I need to understand it better, perhaps.

2020-10-28T16:16:09.039600Z

clojure.lang.PersistentVector

2020-10-28T16:17:14.040600Z

java.lang.Object is in every JVM, whether Clojure is running or not. It is the class from which all other classes are sub-classes (perhaps through a chain of multiple other intermediate classes)

Jim Newton 2020-10-28T16:17:58.041400Z

great.. is there some class which inherits from clojure.lang.PersistentVector ?

2020-10-28T16:18:18.041800Z

If you go through the source directory here, you can probably find a bunch, all in the clojure.lang package: https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang

Jim Newton 2020-10-28T16:18:21.041900Z

ie. a subclass of clojure.lang.PersistentVector ?

2020-10-28T16:18:46.042400Z

I do not know of any off hand. Perhaps not in Clojure itself, but some third party library very well might.

Jim Newton 2020-10-28T16:25:37.043Z

again if it were possible to walk the instances of java.lang.Class I could programmatically find such cases.

seancorfield 2020-10-28T16:28:01.043700Z

@jimka.issy FWIW, most things that need to be "vector-like" extend APersistentVector which is:

public abstract class APersistentVector extends AFn implements IPersistentVector, Iterable,
                                                               List,
                                                               RandomAccess, Comparable,
                                                               Serializable, IHashEq {

seancorfield 2020-10-28T16:28:30.044200Z

Then PersistentVector extends that and implements a few extra interfaces:

public class PersistentVector extends APersistentVector implements IObj, IEditableCollection, IReduce, IKVReduce{

Jim Newton 2020-10-28T16:33:17.044500Z

clojure-rte.rte-core&gt; (:flags (refl/type-reflect clojure.lang.PersistentVector))
#{:public}
clojure-rte.rte-core&gt; (:flags (refl/type-reflect clojure.lang.APersistentVector))
#{:public :abstract}
clojure-rte.rte-core&gt; (:flags (refl/type-reflect clojure.lang.IPersistentVector))
#{:interface :public :abstract}
clojure-rte.rte-core&gt; 

Jim Newton 2020-10-29T07:09:07.051100Z

Can someone suggest a better name for this function? The function takes a class-name such as the symbol Number , uses resolve to get the class and then uses (comp :flags efl/type-reflect) to get a list of flags. Then returns a keyword from :abstract, :interface, :final, :public . My function has a really bad name at the moment. I need a better name for this.

(defn-memoized [class-type -class-type]
  "Takes a class-name and returns either :abstract, :interface, :public, or :final,
  or throws an ex-info exception."
  [t]
  (let [c (find-class t)
        r (refl/type-reflect c)
        flags (:flags r)]
    (cond
      (= c Object) ; case #1
      :abstract
      (contains? flags :interface) ; case #2
      :interface
      (contains? flags :final) ; case #3
      :final
      (contains? flags :abstract) ; case #4
      :abstract
      (= flags #{:public}) ; case #5
      :public
      
      :else
      (throw (ex-info (format "disjoint? type %s flags %s not yet implemented" t flags)
                      {:error-type :invalid-type-flags
                       :a-type t
                       :flags flags})))))
BTW, the function makes a special case of Object, when I'm still not sure is correct for my application. The more I think about it, the more I think case 1 and 5 should be merged into a single case. That might change in the future when I understand the situation better.

Jim Newton 2020-10-28T16:34:03.045Z

@seancorfield do you know of a subclass of clojure.lang.PersistentVector)

Jim Newton 2020-10-28T16:34:18.045300Z

such would be great for a test case of my code

Jim Newton 2020-10-28T16:42:54.045700Z

I found an interesting one:

clojure-rte.rte-core&gt; (:flags (refl/type-reflect BigInteger))
#{:public}
clojure-rte.rte-core&gt; 

seancorfield 2020-10-28T17:00:56.046900Z

What's "interesting" about BigInteger @jimka.issy?

2020-10-28T17:04:48.048400Z

I found some code that I have used in the past to list most/all classes in a running JVM, but in trying to run it today I seem to have lost the recipe for what command line options when starting the JVM it requires to have the right privileges to work properly. It is some test code in this repository: https://github.com/jafingerhut/cljol

2020-10-28T17:05:32.048700Z

A tiny shell script that might work with some operating system / JDK versions, or did at one point, is in the file doc/generate-report.sh

2020-10-28T17:06:20.048900Z

It loads and runs a function named report in this namespace: https://github.com/jafingerhut/cljol/blob/master/src/clj/cljol/reflection_test_helpers.clj

2020-10-28T17:08:51.049300Z

it uses this library to do the actual finding of Java classses and I believe also interfaces: https://github.com/classgraph/classgraph

alexmiller 2020-10-28T17:31:04.049700Z

all of the A... types in clojure are generally base classes, I would guess most are abstract

2020-10-28T17:38:53.049900Z

Here is a short sample use of calling the classgraph library from Clojure, with no other libraries required except classgraph and those included with Clojure: https://github.com/jafingerhut/cljol/blob/master/doc/sample-classgraph-use.clj

Jim Newton 2020-10-28T19:25:19.050300Z

and and I... classes are interfaces?

alexmiller 2020-10-28T19:25:52.050500Z

yes, that's a common Java idiom

alexmiller 2020-10-28T19:26:03.050700Z

(the A... is not, but it's common in the Clojure code base)

alexmiller 2020-10-28T19:26:33.050900Z

which is not to say that it's totally followed - things like Countable are interfaces too