Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #26606 > unrolled thread
| Started by | Saxo <jeti789@web.de> |
|---|---|
| First post | 2013-11-25 03:09 -0800 |
| Last post | 2013-11-28 12:50 -0800 |
| Articles | 14 on this page of 54 — 15 participants |
Back to article view | Back to comp.lang.java.programmer
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]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2013-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]
| From | v_borchert@despammed.com (Volker Borchert) |
|---|---|
| Date | 2013-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]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2013-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]
| From | v_borchert@despammed.com (Volker Borchert) |
|---|---|
| Date | 2013-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]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2013-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]
| From | Joshua Cranmer π§ <Pidgeot18@verizon.invalid> |
|---|---|
| Date | 2013-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]
| From | Joshua Cranmer π§ <Pidgeot18@verizon.invalid> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Joshua Cranmer π§ <Pidgeot18@verizon.invalid> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Joshua Cranmer π§ <Pidgeot18@verizon.invalid> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2014-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]
| From | v_borchert@despammed.com (Volker Borchert) |
|---|---|
| Date | 2013-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]
| From | Roedy Green <see_website@mindprod.com.invalid> |
|---|---|
| Date | 2013-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