Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #26606 > unrolled thread

Alternatives languages on the JVM: which one or is there no alternative?

Started bySaxo <jeti789@web.de>
First post2013-11-25 03:09 -0800
Last post2013-11-28 12:50 -0800
Articles 14 on this page of 54 — 15 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-11-25 03:09 -0800
    Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-25 12:46 +0100
      Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-11-25 05:20 -0800
      Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-11-25 22:10 +0100
        Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-11-25 14:34 -0800
        Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-26 08:54 +0100
          Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-11-26 00:29 -0800
            Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-26 15:29 +0100
              Re: Alternatives languages on the JVM: which one or is there no alternative? Arne VajhΓΈj <arne@vajhoej.dk> - 2013-11-26 21:55 -0500
                Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-27 08:59 +0100
                  Re: Alternatives languages on the JVM: which one or is there no alternative? Joerg Meier <joergmmeier@arcor.de> - 2013-11-27 10:41 +0100
                    Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-28 12:48 +0100
                      Re: Alternatives languages on the JVM: which one or is there no alternative? leif.roar@invalid.com (Leif Roar Moldskred) - 2013-11-28 16:28 -0600
                        Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-29 00:03 +0100
                          Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-11-29 00:41 -0800
                            Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-29 12:05 +0100
                              Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-11-29 03:51 -0800
                                Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-29 16:44 +0100
                                  Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-11-29 16:48 +0100
                                Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-12-02 06:33 -0800
                                  Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-12-02 15:50 +0100
                                    Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-12-02 16:26 +0100
                                      Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-12-02 21:07 +0100
                                        Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-12-02 23:33 +0100
                                        Re: Alternatives languages on the JVM: which one or is there no alternative? markspace <markspace@nospam.nospam> - 2013-12-02 18:07 -0800
                                          Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-12-03 08:59 +0100
                                          Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-12-03 00:14 -0800
                                            Re: Alternatives languages on the JVM: which one or is there no alternative? Silvio <silvio@internet.com> - 2013-12-03 09:42 +0100
                                              Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-12-03 02:58 -0800
                                                Re: Alternatives languages on the JVM: which one or is there no alternative? Martin Gregorie <martin@address-in-sig.invalid> - 2013-12-03 20:55 +0000
                                                  Re: Alternatives languages on the JVM: which one or is there no alternative? Saxo <jeti789@web.de> - 2013-12-04 00:12 -0800
                                                  Re: Alternatives languages on the JVM: which one or is there no alternative? Arved Sandstrom <asandstrom2@eastlink.ca> - 2013-12-14 03:31 -0400
                                                    Re: Alternatives languages on the JVM: which one or is there no alternative? Martin Gregorie <martin@address-in-sig.invalid> - 2013-12-14 10:11 +0000
                                                    Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-12-14 17:39 +0100
                                                      Re: Alternatives languages on the JVM: which one or is there no alternative? "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> - 2013-12-14 16:52 +0000
                                                      Re: Alternatives languages on the JVM: which one or is there no alternative? Arved Sandstrom <asandstrom2@eastlink.ca> - 2013-12-14 13:47 -0400
                                                        Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-12-14 23:55 +0100
                                          Re: Alternatives languages on the JVM: which one or is there no alternative? Sebastian <news@seyweiler.dyndns.org> - 2013-12-04 10:39 +0100
                                            Re: Alternatives languages on the JVM: which one or is there no alternative? Arved Sandstrom <asandstrom2@eastlink.ca> - 2013-12-14 03:56 -0400
    Re: Alternatives languages on the JVM: which one or is there no alternative? v_borchert@despammed.com (Volker Borchert) - 2013-11-26 21:28 +0000
      Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-11-26 23:29 +0100
        Re: Alternatives languages on the JVM: which one or is there no alternative? v_borchert@despammed.com (Volker Borchert) - 2013-11-27 05:13 +0000
          Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-11-27 22:57 +0100
            Re: Alternatives languages on the JVM: which one or is there no alternative? v_borchert@despammed.com (Volker Borchert) - 2013-11-29 23:22 +0000
              Re: Alternatives languages on the JVM: which one or is there no alternative? Robert Klemme <shortcutter@googlemail.com> - 2013-11-30 14:41 +0100
              Re: Alternatives languages on the JVM: which one or is there no alternative? Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> - 2013-11-30 16:49 -0600
          Re: Alternatives languages on the JVM: which one or is there no alternative? Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> - 2013-11-27 23:07 -0600
            Re: Alternatives languages on the JVM: which one or is there no alternative? Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-28 23:41 +0000
              Re: Alternatives languages on the JVM: which one or is there no alternative? Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> - 2013-11-29 00:08 -0600
                Re: Alternatives languages on the JVM: which one or is there no alternative? Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-29 16:49 +0000
                  Re: Alternatives languages on the JVM: which one or is there no alternative? Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> - 2013-11-30 16:46 -0600
                    Re: Alternatives languages on the JVM: which one or is there no alternative? Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2014-02-14 15:36 +0000
            Re: Alternatives languages on the JVM: which one or is there no alternative? v_borchert@despammed.com (Volker Borchert) - 2013-11-29 23:37 +0000
    Re: Alternatives languages on the JVM: which one or is there no alternative? Roedy Green <see_website@mindprod.com.invalid> - 2013-11-28 12:50 -0800

Page 3 of 3 — ← Prev page 1 2 [3]


#26629

FromRobert Klemme <shortcutter@googlemail.com>
Date2013-11-26 23:29 +0100
Message-ID<bfklnaFis1vU1@mid.individual.net>
In reply to#26627
On 26.11.2013 22:28, Volker Borchert wrote:
> No language that is to run on the JVM can overcome its fundamental
> shortcoming of missing multiple implementation inheritance.

I have come to believe that omitting things that other languages do was 
actually a wise decision of the language designers.  Avoiding MI might 
be one of them.  Granted, you cannot use implementation inheritance. 
But sometimes not making these things easy is actually an advantage.  At 
least I think that when comparing C++ and Java.  The equation might 
calculate differently when comparing Java to other languages (Eiffel?).

> While
> this might not be a problem with everyday code, is _is_ a problem
> if you are in low-level or framework stuff, for example if you have
> class hierarchies where you want to offer mixed reference flavors -
> your class C either ends up with two fields, one T and one to some
> (X extends WeakReference<T>) which contains another extra field for
> the back reference to the containing C so that the C can be notified
> of the X having been garbage collected and an extra two-word object
> header, or with lots of duplicated code.

What's wrong with this?

class Foo<T> {
   private Object ref;

   protected T getItem() {
     return ref instanceof WekReference<?> ?
       ((WeakReference<T>) ref).get() :
       (T) ref;
   }

   public T doSomeWork() {
     final T x = getItem();
     // work ...
     return x;
   }

}

Then you need a pair of setters or one setter and one method which 
switches reference mode.  This avoids having two fields and it avoids 
"lots of duplicated code".

I do not know your notification requirements but I am sure you are aware 
of ReferenceQueue.  Do you need notification the very moment an object 
is collected?  How do you do that?  The only way I can think of is 
having an additional thread blocking in ReferenceQueue.remove().  Not 
sure though why I then would place a field in the WeakReference - 
wouldn't it make more sense to let T know of its container / owner?

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#26635

Fromv_borchert@despammed.com (Volker Borchert)
Date2013-11-27 05:13 +0000
Message-ID<l73v2h$f22$1@Gaia.teknon.de>
In reply to#26629
Robert Klemme wrote:
> On 26.11.2013 22:28, Volker Borchert wrote:
> > No language that is to run on the JVM can overcome its fundamental
> > shortcoming of missing multiple implementation inheritance.
> 
> I have come to believe that omitting things that other languages do was 
> actually a wise decision of the language designers.  Avoiding MI might 
> be one of them.  Granted, you cannot use implementation inheritance. 
> But sometimes not making these things easy is actually an advantage.  At 
> least I think that when comparing C++ and Java.  The equation might 
> calculate differently when comparing Java to other languages (Eiffel?).

Maybe so, but then why did the make multihreading - which is even
easier to get really wrong - so easy to use... OO without MI is like
a Ford Mustang with a two cylinder two stroke engine. Yes, it might
eventually take you from A to B, but is it fun?

> What's wrong with this?
> 
> class Foo<T> {
>    private Object ref;
> 
>    protected T getItem() {
>      return ref instanceof WekReference<?> ?
>        ((WeakReference<T>) ref).get() :
>        (T) ref;
>    }
> 
>    public T doSomeWork() {
>      final T x = getItem();
>      // work ...
>      return x;
>    }
> 
> }

BTDT

> Then you need a pair of setters or one setter and one method which 
> switches reference mode.  This avoids having two fields and it avoids 
> "lots of duplicated code".

You still have an extra two-word object header, and you cannot use
WeakReference<T> directly if you want the Foo to act on the
reference being cleared by garbage collection. These 24 extra bytes
hurt if you are doing low-level stuff and expect some tens or
hundreds of thousands of Foo.

Why do you think Java got generally known to be slow and bloated?

getItem() above actually checks for assignment compatibility TWICE -
once for the instanceof and once for the actual cast. JIT should
mitigate this, but I'd still like to have dynamic_cast

> I do not know your notification requirements but I am sure you are aware 
> of ReferenceQueue.

Yes, of course, but ReferenceQueue.poll() returns the Reference<T>,
not the Foo, so for the Foo to act, you need something like

class Foo<T> {
    // nonstatic inner class uzes 4 bytes for the
    // implicit this$0 and 4 more bytes padding
    class TPtr<T> extends WeakReference<T> {
        Foo foo() {
            return Foo.this;
        }
    }

    void gced() {
    }
}

to do something like

    ...
    while ((ref = queue.poll()) != null) {
        ((TPtr<T>) ref).foo().gced();
    }
    ...

> How do you do that?  The only way I can think of is 
> having an additional thread blocking in ReferenceQueue.remove().

BTDT

> wouldn't it make more sense to let T know of its container / owner?

Why? What for?

-- 

"I'm a doctor, not a mechanic." Dr Leonard McCoy <mccoy@ncc1701.starfleet.fed>
"I'm a mechanic, not a doctor." Volker Borchert  <v_borchert@despammed.com>

[toc] | [prev] | [next] | [standalone]


#26644

FromRobert Klemme <shortcutter@googlemail.com>
Date2013-11-27 22:57 +0100
Message-ID<bfn86fF4te5U1@mid.individual.net>
In reply to#26635
On 27.11.2013 06:13, Volker Borchert wrote:
> Robert Klemme wrote:
>> On 26.11.2013 22:28, Volker Borchert wrote:
>>> No language that is to run on the JVM can overcome its fundamental
>>> shortcoming of missing multiple implementation inheritance.
>>
>> I have come to believe that omitting things that other languages do was
>> actually a wise decision of the language designers.  Avoiding MI might
>> be one of them.  Granted, you cannot use implementation inheritance.
>> But sometimes not making these things easy is actually an advantage.  At
>> least I think that when comparing C++ and Java.  The equation might
>> calculate differently when comparing Java to other languages (Eiffel?).
>
> Maybe so, but then why did the make multihreading - which is even
> easier to get really wrong - so easy to use...

Probably because MT is necessary given physical limits to what a single 
CPU can do.

 > OO without MI is like
 > a Ford Mustang with a two cylinder two stroke engine. Yes, it might
 > eventually take you from A to B, but is it fun?

Why do you use Java if you dislike it so much?

>> Then you need a pair of setters or one setter and one method which
>> switches reference mode.  This avoids having two fields and it avoids
>> "lots of duplicated code".
>
> You still have an extra two-word object header, and you cannot use
> WeakReference<T> directly if you want the Foo to act on the
> reference being cleared by garbage collection. These 24 extra bytes
> hurt if you are doing low-level stuff and expect some tens or
> hundreds of thousands of Foo.

It's totally unclear what you mean by "low level stuff".

> Why do you think Java got generally known to be slow and bloated?

Probably because a) computers had less memory and CPU power at the time 
it entered the stage and b) the JVM was far less efficient than it is today.

> getItem() above actually checks for assignment compatibility TWICE -
> once for the instanceof and once for the actual cast. JIT should
> mitigate this, but I'd still like to have dynamic_cast

What does dynamic_cast in C++ do differently?  As far as I am informed 
it involves a type check as well.  I mean, you can have the same in Java 
by catching the exception (which is what you need to do in C++ IIRC).

>> I do not know your notification requirements but I am sure you are aware
>> of ReferenceQueue.
>
> Yes, of course, but ReferenceQueue.poll() returns the Reference<T>,
> not the Foo, so for the Foo to act, you need something like
>
> class Foo<T> {
>      // nonstatic inner class uzes 4 bytes for the
>      // implicit this$0 and 4 more bytes padding
>      class TPtr<T> extends WeakReference<T> {
>          Foo foo() {
>              return Foo.this;
>          }
>      }
>
>      void gced() {
>      }
> }

Since Foo inherits Object you could as well make Foo<T> inherit 
WeakReference<T> avoiding the additional bytes per instance.  And it's 
basically what Foo seems to be: a reference to a T - so it's actually 
not too far fetched.

> to do something like
>
>      ...
>      while ((ref = queue.poll()) != null) {
>          ((TPtr<T>) ref).foo().gced();
>      }
>      ...

What does that thread do outside this loop?

>> How do you do that?  The only way I can think of is
>> having an additional thread blocking in ReferenceQueue.remove().
>
> BTDT

And why did it not work for you?

>> wouldn't it make more sense to let T know of its container / owner?
>
> Why? What for?

Since Foo references the other object there seems to be a business 
relationship between the two.  T would then need to be bound by an 
interface.

I find it difficult to discuss this without knowing more about your 
requirements and situation.  But then again, maybe you don't want or 
cannot disclose that.

Cheers

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#26676

Fromv_borchert@despammed.com (Volker Borchert)
Date2013-11-29 23:22 +0000
Message-ID<l7b7jt$j0j$1@Gaia.teknon.de>
In reply to#26644
Robert Klemme wrote:

> What does dynamic_cast in C++ do differently?  As far as I am informed 
> it involves a type check as well.  I mean, you can have the same in Java 
> by catching the exception (which is what you need to do in C++ IIRC).

No you don't, that is exactly the raison d'etre of dynamic_cast.

  if (o instanceof C) {
    final C c = (C) o;
    // do something with c
  }

does _two_ typechecks

  final C c = dynamic_cast<C>(o);
  if (c != null) {
    // do something with c
  }

would do _one_ typecheck and a cheap IFNONNULL

> > class Foo<T> {
> >      // nonstatic inner class uzes 4 bytes for the
> >      // implicit this$0 and 4 more bytes padding
> >      class TPtr<T> extends WeakReference<T> {
> >          Foo foo() {
> >              return Foo.this;
> >          }
> >      }
> >
> >      void gced() {
> >      }
> > }
> 
> Since Foo inherits Object you could as well make Foo<T> inherit 
> WeakReference<T> avoiding the additional bytes per instance.

Sorry, I forgot the "extends Bar<T>".

> I find it difficult to discuss this without knowing more about your 
> requirements and situation.  But then again, maybe you don't want or 
> cannot disclose that.

One example, for a Cache<Key,Value> that supports mixed flavor Value
references, and a subclass which additionally has entries doubly
linked, somewhat similar to LinkedHashMap, I want

                     AbstractEntry<K,V>                 WeakReference<V>
                            |                                    |
                            |                                    |
                           / \                                   |
          +---------------+---+----------+-------------+         |
          |                              |             |         |
          |                              |             |         |
  AbstractLinkedEntry<K,V>         StrongEntry<K,V>    |         |
          |                              |             |         |
          |                              |             |         |
          +---------------+---+----------+             +--+---+--+
          |                \ /                             \ /
          |                 |                               |
          |                 |                               |
          |          StrongLinkedEntry<K,V>             WeakEntry<K,V>
          |                                                 |
          |                                                 |
          +------------------------------+---+--------------+
                                          \ /
                                           |
                                           |
                                     WeakLinkedEntry<K,V>


(soft flavor omitted for safe of readability)


-- 

"I'm a doctor, not a mechanic." Dr Leonard McCoy <mccoy@ncc1701.starfleet.fed>
"I'm a mechanic, not a doctor." Volker Borchert  <v_borchert@despammed.com>

[toc] | [prev] | [next] | [standalone]


#26686

FromRobert Klemme <shortcutter@googlemail.com>
Date2013-11-30 14:41 +0100
Message-ID<bfu88jFj71rU1@mid.individual.net>
In reply to#26676
On 30.11.2013 00:22, Volker Borchert wrote:
> Robert Klemme wrote:
>
>> What does dynamic_cast in C++ do differently?  As far as I am informed
>> it involves a type check as well.  I mean, you can have the same in Java
>> by catching the exception (which is what you need to do in C++ IIRC).
>
> No you don't, that is exactly the raison d'etre of dynamic_cast.
>
>    if (o instanceof C) {
>      final C c = (C) o;
>      // do something with c
>    }
>
> does _two_ typechecks
>
>    final C c = dynamic_cast<C>(o);
>    if (c != null) {
>      // do something with c
>    }
>
> would do _one_ typecheck and a cheap IFNONNULL

I was only aware of the exception thrown from dynamic_cast - but that is 
only the case for reference types.  Thanks for the update!

I have no idea how these really compare performance wise: there is JIT 
and then I do not know how expensive the type check is really.  The best 
would be to make _realistic_ measurements of the type checking overhead.

>> I find it difficult to discuss this without knowing more about your
>> requirements and situation.  But then again, maybe you don't want or
>> cannot disclose that.
>
> One example, for a Cache<Key,Value> that supports mixed flavor Value
> references, and a subclass which additionally has entries doubly
> linked, somewhat similar to LinkedHashMap, I want
>
>                       AbstractEntry<K,V>                 WeakReference<V>
>                              |                                    |
>                              |                                    |
>                             / \                                   |
>            +---------------+---+----------+-------------+         |
>            |                              |             |         |
>            |                              |             |         |
>    AbstractLinkedEntry<K,V>         StrongEntry<K,V>    |         |
>            |                              |             |         |
>            |                              |             |         |
>            +---------------+---+----------+             +--+---+--+
>            |                \ /                             \ /
>            |                 |                               |
>            |                 |                               |
>            |          StrongLinkedEntry<K,V>             WeakEntry<K,V>
>            |                                                 |
>            |                                                 |
>            +------------------------------+---+--------------+
>                                            \ /
>                                             |
>                                             |
>                                       WeakLinkedEntry<K,V>
>
>
> (soft flavor omitted for safe of readability)

So if I understand your diagram correctly you want to mix two 
implementation aspects
1. weak or strong referencing
2. linked and not linked entries (probably for LRU scheme)

Given what I know so far I'd still do it as suggested earlier: use an 
Object field to either reference the item or a WeakReference.  If that 
overhead compared to the cached keys and values is significant then, 
yes, that might be something to worry about.  If on the other hand you 
are caching contents of Icon files I wouldn't think about that overhead.

The linked entry class would then be a sub class of the simple reference 
and contain everything necessary for managing the linked list of entries.

If a single cache has uniform entries then you can avoid the type 
checking with instanceof and just cast.  The algorithmic part could even 
be abstracted away via an interface referenced by the cache instance. 
For the strong reference type you would end up with the single cast that 
appears outside the cache when the reference is assigned a variable of a 
specific type; type erasure will make all V things Object inside the cache.

Now we just need to know what you want to do with this and why you need 
to be asynchronously notified of GC'ed entries. :-)

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#26692

FromJoshua Cranmer 🐧 <Pidgeot18@verizon.invalid>
Date2013-11-30 16:49 -0600
Message-ID<l7dq27$fu0$2@dont-email.me>
In reply to#26676
On 11/29/2013 5:22 PM, Volker Borchert wrote:
> Robert Klemme wrote:
>
>> What does dynamic_cast in C++ do differently?  As far as I am informed
>> it involves a type check as well.  I mean, you can have the same in Java
>> by catching the exception (which is what you need to do in C++ IIRC).
>
> No you don't, that is exactly the raison d'etre of dynamic_cast.
>
>    if (o instanceof C) {
>      final C c = (C) o;
>      // do something with c
>    }
>
> does _two_ typechecks

For any optimizer that can do basic CSE (which is any optimizer that 
anyone would not be ashamed to make publicly available), the second 
typecheck can be trivially eliminated.

-- 
Beware of bugs in the above code; I have only proved it correct, not 
tried it. -- Donald E. Knuth

[toc] | [prev] | [next] | [standalone]


#26650

FromJoshua Cranmer 🐧 <Pidgeot18@verizon.invalid>
Date2013-11-27 23:07 -0600
Message-ID<l76j3e$27f$1@dont-email.me>
In reply to#26635
On 11/26/2013 11:13 PM, Volker Borchert wrote:
> You still have an extra two-word object header, and you cannot use
> WeakReference<T> directly if you want the Foo to act on the
> reference being cleared by garbage collection. These 24 extra bytes
> hurt if you are doing low-level stuff and expect some tens or
> hundreds of thousands of Foo.

And you think multiple inheritance has no costs? The moment you allow 
multiple inheritance of implementations, you permit the so-called 
"diamond problem." The diamond problem has three solutions:
1. There are multiple copies of some fields.
2. Offsets to a particular named field are dependent on object 
instances, not on classes/class hierarchies.
3. Casting up or down a tree requires recomputing offsets on a 
per-object instance basis, not a per-class basis.

The first case only affects classes that are involved in the diamond 
problem, but the effects are so egregiously awful (in the case where 
data is actually present) that it is prudent to outlaw it from 
happening. The latter two cases impose a performance penalty on the 
entire program, even if the diamond problem never arises: you're paying 
for what you don't use.

Multiple inheritance is a seductive call. There are very, very, very few 
times where it is actually proper--recall that inheritance, at least as 
Java is concerned, is meant to model an "is-a" relationship, not a 
"has-a" relationship. Since inheritance is an indelible part of the 
public contract of a class in Java, the "is implemented in terms of" 
relationship is supposed to be handled via composition (cf., Effective 
Java). Let the JIT and the optimizer work through the overhead; 
premature optimization, after all, is the root of all evil.

-- 
Beware of bugs in the above code; I have only proved it correct, not 
tried it. -- Donald E. Knuth

[toc] | [prev] | [next] | [standalone]


#26656

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-28 23:41 +0000
Message-ID<slrnl9fl5c.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26650
Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> wrote:
> And you think multiple inheritance has no costs? The moment you allow 
> multiple inheritance of implementations, you permit the so-called 
> "diamond problem." The diamond problem has three solutions:
> 1. There are multiple copies of some fields.
> 2. Offsets to a particular named field are dependent on object 
> instances, not on classes/class hierarchies.
> 3. Casting up or down a tree requires recomputing offsets on a 
> per-object instance basis, not a per-class basis.

I think, the diamond problem w.r.t fields is over-rated.

1.: It's like a plain tree-shaped class hierarchy, where multiple classes
in a vertical chain may already have non-private equally-named fields.
And the jvm is quite good at keeping these separate...
2.: It would still only depend on the Object's getClass(), not
on each individual instance.
3.: Only casts along an "is-*also*-a"-line would need to know some
offset, and the compiler already masters harder problems than that.

Just recently I came a cross a configuration of entities akin to 

mammal | egg-layer
    \      /
    platypus

and I will probably need to decide on one super class, then
duplicate some code (even if just as stubs) to get the other
candidate super-class' code in.

> Multiple inheritance is a seductive call. There are very, very, very few 
> times where it is actually proper--recall that inheritance, at least as 
> Java is concerned, is meant to model an "is-a" relationship, not a 
> "has-a" relationship.

So, if some entity "is-a"nother entity, but "is-also-a" yet another 
entity, then why is Java praised for forcing me to model an "is-also-a"
relation as a "has-a"?

[toc] | [prev] | [next] | [standalone]


#26659

FromJoshua Cranmer 🐧 <Pidgeot18@verizon.invalid>
Date2013-11-29 00:08 -0600
Message-ID<l79b0f$ipg$1@dont-email.me>
In reply to#26656
On 11/28/2013 5:41 PM, Andreas Leitgeb wrote:
> Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> wrote:
>> And you think multiple inheritance has no costs? The moment you allow
>> multiple inheritance of implementations, you permit the so-called
>> "diamond problem." The diamond problem has three solutions:
>> 1. There are multiple copies of some fields.
>> 2. Offsets to a particular named field are dependent on object
>> instances, not on classes/class hierarchies.
>> 3. Casting up or down a tree requires recomputing offsets on a
>> per-object instance basis, not a per-class basis.
>
> I think, the diamond problem w.r.t fields is over-rated.

Given your response below, I think you misunderstand the problem. Let me 
try to explain it better. There are two separate issues: name 
resolution, and class layout. Name resolution is relatively simple to 
solve; it's the layout that is the thorny solution.

When you layout a class in memory, it is easiest to think of it as an 
array of "slots" for actual field storage (think C structs if you're 
used to that). Class layout is typically done by laying out the 
superclass first and then using extra slots for the subclass. If done 
this way, this lets you guarantee that all objects of class A, slot 0 
always points to the same field, even if the object's dynamic type is 
really a subclass of A.

Multiple inheritance throws a wrinkle into this scheme because of the 
diamond problem. If D inherits from B and C, which both inherit from A, 
then the standard way of laying out the class yields two copies of A. If 
you cast D to type C, then a method of C that tries to access a field of 
type A would access C's copy of A instead of B (and presumably D's 
"primary" copy)'s copy. This is the first case I give. In this 
situation, accessing a field only requires knowing the static type of 
the object, not the dynamic type.

You can get around this by requiring knowledge about dynamic types. The 
option taken by C++'s virtual bases is to have the class layout 
mechanism create only one copy of A. In this case, there is no longer a 
guarantee that the field is always at the same offset for the static 
type of an object--you have to do a layer of indirection to find out 
where A's slots are and then use those. This is case #3 (note that the 
casting to use a superclass's fields is implicit here).

The final option is to refer to fields internally via a hashtable of 
(qualified) name to their values. This is generally what is done in most 
dynamic programming languages (Python, JS, etc.), which is why they can 
suffer multiple inheritance: all property accesses already go through 
the hashtable, so there is no extra cost. This is what I called case #2.

>> Multiple inheritance is a seductive call. There are very, very, very few
>> times where it is actually proper--recall that inheritance, at least as
>> Java is concerned, is meant to model an "is-a" relationship, not a
>> "has-a" relationship.
>
> So, if some entity "is-a"nother entity, but "is-also-a" yet another
> entity, then why is Java praised for forcing me to model an "is-also-a"
> relation as a "has-a"?

There are certainly cases where multiple inheritance is warranted; I am 
not disputing that. That said, there are also people who try to inherit 
for the wrong reasons, so probably most cases where people think they 
want to use multiple inheritance, they don't. (I'm speaking in 
generalities, though, and all generalities are false).

-- 
Beware of bugs in the above code; I have only proved it correct, not 
tried it. -- Donald E. Knuth

[toc] | [prev] | [next] | [standalone]


#26669

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-29 16:49 +0000
Message-ID<slrnl9hhdd.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26659
Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> wrote:
> On 11/28/2013 5:41 PM, Andreas Leitgeb wrote:
>> Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> wrote:
>>> And you think multiple inheritance has no costs? The moment you allow
>>> multiple inheritance of implementations, you permit the so-called
>>> "diamond problem." The diamond problem has three solutions:
>>> 1. There are multiple copies of some fields.
>>> 2. Offsets to a particular named field are dependent on object
>>> instances, not on classes/class hierarchies.
>>> 3. Casting up or down a tree requires recomputing offsets on a
>>> per-object instance basis, not a per-class basis.
>> I think, the diamond problem w.r.t fields is over-rated.
> Given your response below, I think you misunderstand the problem.

My response was already trimmed a bit, so may not have completely
reflected my level of understanding it.

> Let me try to explain it better. There are two separate issues: name 
> resolution, and class layout. Name resolution is relatively simple to 
> solve; it's the layout that is the thorny solution.
ok.

> When you layout a class in memory, it is easiest to think of it as an 
> array of "slots" for actual field storage (think C structs if you're 
> used to that). Class layout is typically done by laying out the 
> superclass first and then using extra slots for the subclass.

While C++ doesn't (or didn't) always keep RTTI (for the eventual
by-reader: "run time type info"),  Java *always* knows of what class
any instance really is, so most of the price necessary for multi-
inheritence is already paid for in Java-world.

> Multiple inheritance throws a wrinkle into this scheme because of the 
> diamond problem. If D inherits from B and C, which both inherit from A, 
> then the standard way of laying out the class yields two copies of A.

That would have been my preferred MI approach for Java...

There are of course problems to solve, but they can be solved by 
definitions: "if not unique, pick the first one along the super-class
list that qualifies". If a particular grandsuperclass is wanted, there
would need to be some qualification syntax for it.

I'm not going to break my head on implementation details of how
a particular field would be located in the slots. I'd assume that
even if there is some extra offset that would need to be checked,
then the hotspot JIT compiler would surely do a good job on eliding
it for all "is-primarily-a" relations.

>>> Multiple inheritance is a seductive call.
> There are certainly cases where multiple inheritance is warranted;
> [ ... and cases, where ppl *think* it is, but isn't. ]
This surely wouldn't be the only feature that could be used or misused...

[toc] | [prev] | [next] | [standalone]


#26691

FromJoshua Cranmer 🐧 <Pidgeot18@verizon.invalid>
Date2013-11-30 16:46 -0600
Message-ID<l7dpsg$fu0$1@dont-email.me>
In reply to#26669
On 11/29/2013 10:49 AM, Andreas Leitgeb wrote:
> Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> wrote:
>> On 11/28/2013 5:41 PM, Andreas Leitgeb wrote:
>> When you layout a class in memory, it is easiest to think of it as an
>> array of "slots" for actual field storage (think C structs if you're
>> used to that). Class layout is typically done by laying out the
>> superclass first and then using extra slots for the subclass.
>
> While C++ doesn't (or didn't) always keep RTTI (for the eventual
> by-reader: "run time type info"),  Java *always* knows of what class
> any instance really is, so most of the price necessary for multi-
> inheritence is already paid for in Java-world.

RTTI doesn't enter into the picture. The problems it solves are 
downcasts and reflection. The problem is doing an upcast between two 
classes, neither of which are the most derived type of a class. Even in 
C++, the most derived type is easy to find (it's the vtable pointer).
>
>> Multiple inheritance throws a wrinkle into this scheme because of the
>> diamond problem. If D inherits from B and C, which both inherit from A,
>> then the standard way of laying out the class yields two copies of A.
>
> That would have been my preferred MI approach for Java...

This approach means that following statement holds:
D d = new D();
(A)(B)d != (A)(C)d;

The point is that the "identity" of casting an object to a superclass 
depends on the path through which you do it.

> I'm not going to break my head on implementation details of how
> a particular field would be located in the slots. I'd assume that
> even if there is some extra offset that would need to be checked,
> then the hotspot JIT compiler would surely do a good job on eliding
> it for all "is-primarily-a" relations.

This requires shape analysis and/or devirtualization to be able to 
remove the extra level of indirection. I don't know how well the JVM 
JITs are at doing these nowadays, but when Java was first developed, the 
state of the art in terms of research was pretty much not there to 
eliminate the indirection often enough.

-- 
Beware of bugs in the above code; I have only proved it correct, not 
tried it. -- Donald E. Knuth

[toc] | [prev] | [next] | [standalone]


#27509

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2014-02-14 15:36 +0000
Message-ID<slrnlfsdv2.ngg.avl@gamma.logic.tuwien.ac.at>
In reply to#26691
A late response...

Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> wrote:
> RTTI doesn't enter into the picture. The problems it solves are 
> downcasts and reflection. The problem is doing an upcast between two 
> classes, neither of which are the most derived type of a class. Even in 
> C++, the most derived type is easy to find (it's the vtable pointer).

I knew that RTTI isn't itself necessary, but I thought that as Java has
RTTI already, the need for analysis of non-trivial downcasts wouldn't be
a show stopper.

>>> Multiple inheritance throws a wrinkle into this scheme because of the
>>> diamond problem. If D inherits from B and C, which both inherit from A,
>>> then the standard way of laying out the class yields two copies of A.
>> That would have been my preferred MI approach for Java...
> This approach means that following statement holds:
> D d = new D();
> (A)(B)d != (A)(C)d;

That sure looks surprising :-}

Maybe some restrictions on MI could avoid these cases, while still 
allowing other parts of MI.  Obviously disallowing diamonds altogether
won't cut it, as "Object" would be always there as an "A".  Eventually,
non-primary "is-a" relations would turn into "behaves like a", which
could boil down to treating the non-primary superclasses like interfaces,
except that there would be a way to adopt methods to some degree...
I think I once read about some approach of that kind that was already
more thought out than my utterings here.

[toc] | [prev] | [next] | [standalone]


#26677

Fromv_borchert@despammed.com (Volker Borchert)
Date2013-11-29 23:37 +0000
Message-ID<l7b8gk$j9o$1@Gaia.teknon.de>
In reply to#26650
Joshua Cranmer ???? wrote:

> And you think multiple inheritance has no costs?

No.

> 2. Offsets to a particular named field are dependent on object 
> instances, not on classes/class hierarchies.
> 3. Casting up or down a tree requires recomputing offsets on a 
> per-object instance basis, not a per-class basis.

If they had spent the time wasted on yet another GUI framwork on
these... After all, that's what JIT is good at, isn't it?

> inheritance, at least as 
> Java is concerned, is meant to model an "is-a" relationship, not a 
> "has-a" relationship.

I know. And IMO this holds true generally, not only for Java.

I admit that in my Cache<K,V> example  you could argue that the Entry
_has_ a WeakReference<V> rather than _being_ one. But then, being-a
WeakReference<V> is very similar to weakly-having-a V, isn't it?

> Since inheritance is an indelible part of the 
> public contract of a class in Java,

Another shortcoming of Java, but not necessarily of the JVM - lack of
nonpublic inheritance.

> Let the JIT and the optimizer work through the overhead;

They can't work through the extra memory required for the extra object
needed for aggregation.

> premature optimization, after all, is the root of all evil.

+1

-- 

"I'm a doctor, not a mechanic." Dr Leonard McCoy <mccoy@ncc1701.starfleet.fed>
"I'm a mechanic, not a doctor." Volker Borchert  <v_borchert@despammed.com>

[toc] | [prev] | [next] | [standalone]


#26652

FromRoedy Green <see_website@mindprod.com.invalid>
Date2013-11-28 12:50 -0800
Message-ID<l3bf99l54j2c99c5s96bqekiaokjabf45d@4ax.com>
In reply to#26606
On Mon, 25 Nov 2013 03:09:05 -0800 (PST), Saxo <jeti789@web.de> wrote,
quoted or indirectly quoted someone who said :


>I'm one of the guys that somewhen felt frustrated with Java 

One language you have not yet tried is Ruby. I am not saying it is
what you are looking for, just that it is another possibility.
-- 
Roedy Green Canadian Mind Products http://mindprod.com
Unlike many machines, computers require no water once they are
manufactured.

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.java.programmer


csiph-web