From: Andy McFadden on
In comp.sys.apple2 Paul Schlyter <pausch(a)saaf.se> wrote:
>> Sorry, this isn't true. The Java language specification is quite
>> deliberately void of any language construct that would bind it, or any
>> program written in it to a specific architecture.
>
> Java is not unique in this respect - languages like FORTRAN, C, C++,
> Pascal and Ada are also void of any language construct that would bind
> it, or any program written in it, to a specific architecture. To
> write non-portable programs in these languages you almost always have
> to use implementation specific extensions (with the exception of C and C++,
> where you can use pointes for a lot of architecture dependent stuff -- otoh
> if you read the standards of these languages carefully, the behaviour of
> such programs is described as "undefined").

This is better in, say, C99, which declares the existence of "inttypes.h",
with types like "int32_t" (a signed 32-bit integer).

I've seen FORTRAN code that initialized multiple global arrays, of
varying types, with a single integer "clear memory area to zero" loop.
The author knew exactly how large all of the types were, how they packed,
how they were laid out in memory, what the floating point representation of
"all bits zero" meant, and so on. Any change to the way the compiler
worked would have broken it.

There's nothing implementation-specific about it; the language clearly
allows it. No pointers involved. C/C++ would allow it too. Java does not.

>> Additionally, the language specification defines EXACTLY the size and
>> precision of each data type.
>
> ...which will limit Java to architectures having exactly these sizes and
> precisions of their data types. Do you need 128-bit binary floating-point
> numbers for your number crunching stuff? Forget about Java then.... or
> does your hardware have 1-complement signed integers? Java requires
> integers to be 2-complement, i.e. you must then have some emulation layer
> on top of your native integer format - that's inefficient.

Yes. Java trades portability and safety for efficiency. That's rather
the point of the exercise.

>> It is impossible to write a Java program that's bound to a specific
>> machine architecture.
>
> ...actually, it's quite easy to do that: just use some of the common Java
> class libraries in your program, then try to run it on some architecture
> except the java architecture, i.e. without a JVM ......

With C/C++ the machine architecture and compiler configuration/capabilities
are significant. With gcc on a 32-bit architecture you are likely to get
the same results on multiple platforms, but the "class libraries" can be
different. You're usually okay so long as you stick with POSIX.

With Java we're talking about a virtual machine architecture, which is
the same everywhere. Writing to Java is like knowing that you're always
going to be running on x86 Linux with libc6.

We're getting into a pedantic/semantic argument over what "portability"
means, but I think the rigid definitions of the Java language, VM, and
class libraries make it significantly more likely that you will be able
to write code once and have it run everywhere. And you don't need to
have an autoconf script to make that happen.

>> Many C compilers implement int as a 32 bit quantity even on 64 bit
>> architectures,
>
> Those C compilers aren't follow ANSI C compliant, I would say.

Check the spec.

> C code which assumes a pointer to be of the same size as an int is
> broken. That assumption was invalid already in the 16-bit world,
> where an int naturally was 16 bits while a pointer could be 16 or 32
> bits, depending on the memory model. In one and the same program, a
> function pointer could even be of a different size than a data
> pointer.

It's not broken -- it runs fine on the architecture for which it was
written -- it just isn't portable. This is the argument for Java. If
you believe that code of this nature is actually broken, then you will
be pleased to discover that it is impossible to write broken code of
this type in Java.

> I know about these implementations -- but how well do these non-JVM
> Java compilers run most Java programs originally written for JVM-Java?
> They lack a number of classes in the Java class library, don't they?
> Java is, by itself, such a small language that you cannot do much
> interesting with it without using the Java class libraries.

You actually cannot do anything -- several fundamental types required
by the VM are, in theory, part of the class libraries. The idea is not
to do without the VM or class libraries, but rather to skip the "JIT"
part of compilation.

>> The big issue that existed with Microsofts implementation of Java, was
>> that they extended the language to permit pointer manipulation and
>> direct calls to native code segments, so that you can directly call the
>> Win32 API. This enabled them to easily generate Java stubs for the
>> entire Win32 API.
>
> You can do that also in Sun's Java - just use JNI and some glue C code....

It's not quite as dramatic in JNI. You can get and set types, and do
some fancy things with arrays, but the VM can decide that data should be
copied in and out rather than giving you direct access. The .NET stuff
is more aware of what the VM is doing, which can make it more efficient
but also ties the C# VM to a specific data model.

>> This compromises not only the portability of Java
>> programs, but also the security model provided by the Java platform,
>> which is dependent on programs not being able to access memory that
>> belong to the VM, or any other program that's running in the same
>> memory space.
>
> How well is that security model maintained in GNU's Java implementation
> which runs without any VM and generates native code?

Probably as secure as a VM-based implementation, which is itself just a
bunch of native code.

> Here you compare two platforms. I agree with what you say here, however
> it does illuminate my point: Java isn't platform independent, Java is
> a platform. And here you compare the Java platform with the Windows
> platform. That makes sense. It would not have made sense to compare
> the Windows platform with e.g. C or C++, because they are languages,
> not platforms.

Getting to the pedantic/semantic part. When people say "Java is portable",
they assume that you have a Java VM running on your platform of choice.
Programs running inside the Java VM are portable, but whether or not Java
is available on your Apple II is a different issue.

> Btw, UNIX isn't "a platform". UNIX is a collection of several similar
> platforms which still are different enough to make some programs
> written for e.g. Linux source incompatible with e.g. Free-BSD, HP-UX or AIX.

Java is a collection of several similar platforms (Sun's, GNU classpath,
several commercial versions, some open source versions) running similar
goodies, but each has been limited or extended in some way.

If you think of a "POSIX + gcc" platform, it's fairly similar to Java.

--
Send mail to fadden(a)fadden.com (Andy McFadden) - http://www.fadden.com/
CD-Recordable FAQ - http://www.cdrfaq.org/
CiderPress Apple II archive utility for Windows - http://www.faddensoft.com/
Fight Internet Spam - http://spam.abuse.net/spam/ & http://spamcop.net/
From: Paul Schlyter on
In article <44771e89$0$65426$742ec2ed(a)news.sonic.net>,
Andy McFadden <fadden(a)fadden.com> wrote:

> In comp.sys.apple2 Paul Schlyter <pausch(a)saaf.se> wrote:
>>> Sorry, this isn't true. The Java language specification is quite
>>> deliberately void of any language construct that would bind it, or any
>>> program written in it to a specific architecture.
>>
>> Java is not unique in this respect - languages like FORTRAN, C, C++,
>> Pascal and Ada are also void of any language construct that would bind
>> it, or any program written in it, to a specific architecture. To
>> write non-portable programs in these languages you almost always have
>> to use implementation specific extensions (with the exception of C and C++,
>> where you can use pointes for a lot of architecture dependent stuff -- otoh
>> if you read the standards of these languages carefully, the behaviour of
>> such programs is described as "undefined").
>
> This is better in, say, C99, which declares the existence of "inttypes.h",
> with types like "int32_t" (a signed 32-bit integer).

Somewhat in the spirit of Ada then, where you declare a numeric variable
as the number of decimal digits it should be able to hold, at a minimum.

> I've seen FORTRAN code that initialized multiple global arrays, of
> varying types, with a single integer "clear memory area to zero" loop.
> The author knew exactly how large all of the types were, how they packed,
> how they were laid out in memory, what the floating point representation of
> "all bits zero" meant, and so on. Any change to the way the compiler
> worked would have broken it.

There are indeed a lot of ugly tricks you can do in FORTRAN. A lot of
them involve "interesting" uses of EQUIVALENCE ......

> There's nothing implementation-specific about it; the language clearly
> allows it.

Sorry, but such tricks becomes *very* implementation dependent....

When handling strings in FORTRAN-66, you even HAD to resort to these
tricks. FORTRAN-66 lacked string variables, so strings of characters
had to be stored in arrays of numeric variables. Now, the number of
characters which could be stored in an INTEGER or a REAL varied
between implementation ... on machines with 8-bit bytes and 32-bit
integers or reals one could store 4 characters in each numeric
variable (or 8 characters in a DOUBLE PRECISION or COMPLEX variable),
while on machines with 6-bit bytes and 60-bit integers and reals, one
could store 10 characters in each numeric variable (or 20 characters
in a DOUBLE PRECISION or COMPLEX variable).

> No pointers involved. C/C++ would allow it too.

Yep - C has unions....

> Java does not.

Which is curious, since Java prescribes the way numeris variables should
be represented, it would actually work there.

Otoh Java is too restrictive -- it's a real mess to handle unsigned
data in Java, since Java lacks unsigned integer types.


>>> Additionally, the language specification defines EXACTLY the size and
>>> precision of each data type.
>>
>> ...which will limit Java to architectures having exactly these sizes and
>> precisions of their data types. Do you need 128-bit binary floating-point
>> numbers for your number crunching stuff? Forget about Java then.... or
>> does your hardware have 1-complement signed integers? Java requires
>> integers to be 2-complement, i.e. you must then have some emulation layer
>> on top of your native integer format - that's inefficient.
>
> Yes. Java trades portability and safety for efficiency. That's rather
> the point of the exercise.

Java loses some portability though -- I'm not aware of any JVM targeted
for hardware using 1-complement integer arithmetic, or non-IEEE f.p.
formats. In this respect, C and C++ will be more portable than Java.

>>> It is impossible to write a Java program that's bound to a specific
>>> machine architecture.
>>
>> ...actually, it's quite easy to do that: just use some of the common Java
>> class libraries in your program, then try to run it on some architecture
>> except the java architecture, i.e. without a JVM ......
>
> With C/C++ the machine architecture and compiler configuration/capabilities
> are significant. With gcc on a 32-bit architecture you are likely to get
> the same results on multiple platforms, but the "class libraries" can be
> different. You're usually okay so long as you stick with POSIX.
>
> With Java we're talking about a virtual machine architecture, which is
> the same everywhere.

.....that's called "single platform"....

> Writing to Java is like knowing that you're always
> going to be running on x86 Linux with libc6.

Yep -- another example of single platform development. WHatever
platform you're using, you can write your program for that platform only,
ignoring what might happen the day your program is ported to another
platform.

> We're getting into a pedantic/semantic argument over what "portability"
> means, but I think the rigid definitions of the Java language, VM, and
> class libraries make it significantly more likely that you will be able
> to write code once and have it run everywhere. And you don't need to
> have an autoconf script to make that happen.

No --- Java programs will run only on the Java platform without problems.
And there are even problems between different versions of the JVM: if
you upgrade the JVM to the latest version on your web browser, some older
applets will cease working properly. For that reason, I still keep an
old Netscape 4.7 web browser available, with its own very old JVM, for
applets which won't run on the latest JVM's.

So the claim that "Java programs run everywhere without problems" is
a myth -- even among different JVM's on the same computer!

>> Many C compilers implement int as a 32 bit quantity even on 64 bit
>>> architectures,
>>
>> Those C compilers aren't follow ANSI C compliant, I would say.
>
> Check the spec.

I just did. ANSI X3.159-1989, paragraph "3.1.2.5 Types", says:

# A "plain" int object has the natural size suggested by the
# architecture of the execution environemt.

So do you think 32 bits really is the natural size suggested by a 64
bit architecture?

>> C code which assumes a pointer to be of the same size as an int is
>> broken. That assumption was invalid already in the 16-bit world,
>> where an int naturally was 16 bits while a pointer could be 16 or 32
>> bits, depending on the memory model. In one and the same program, a
>> function pointer could even be of a different size than a data
>> pointer.
>
> It's not broken -- it runs fine on the architecture for which it was
> written -- it just isn't portable. This is the argument for Java. If
> you believe that code of this nature is actually broken, then you will
> be pleased to discover that it is impossible to write broken code of
> this type in Java.

Naturally it's impossible to write code that's broken in this way in
any single-platform language - not just Java.

>> I know about these implementations -- but how well do these non-JVM
>> Java compilers run most Java programs originally written for JVM-Java?
>> They lack a number of classes in the Java class library, don't they?
>> Java is, by itself, such a small language that you cannot do much
>> interesting with it without using the Java class libraries.
>
> You actually cannot do anything -- several fundamental types required
> by the VM are, in theory, part of the class libraries. The idea is not
> to do without the VM or class libraries, but rather to skip the "JIT"
> part of compilation.
>
>>> The big issue that existed with Microsofts implementation of Java, was
>>> that they extended the language to permit pointer manipulation and
>>> direct calls to native code segments, so that you can directly call the
>>> Win32 API. This enabled them to easily generate Java stubs for the
>>> entire Win32 API.
>>
>> You can do that also in Sun's Java - just use JNI and some glue C code....
>
> It's not quite as dramatic in JNI. You can get and set types, and do
> some fancy things with arrays, but the VM can decide that data should be
> copied in and out rather than giving you direct access. The .NET stuff
> is more aware of what the VM is doing, which can make it more efficient
> but also ties the C# VM to a specific data model.

You can reverse engineer a particular JVM, and then use the pointer
given to your C code by JNI, and then do about anything you want inside
the JVM with your C code. Such a situation would be similar to the
..NET situation, where there is one single .NET-VM, written by Microsoft
to run on Windows.

>>> This compromises not only the portability of Java
>>> programs, but also the security model provided by the Java platform,
>>> which is dependent on programs not being able to access memory that
>>> belong to the VM, or any other program that's running in the same
>>> memory space.
>>
>> How well is that security model maintained in GNU's Java implementation
>> which runs without any VM and generates native code?
>
> Probably as secure as a VM-based implementation, which is itself just a
> bunch of native code.
>
>> Here you compare two platforms. I agree with what you say here, however
>> it does illuminate my point: Java isn't platform independent, Java is
>> a platform. And here you compare the Java platform with the Windows
>> platform. That makes sense. It would not have made sense to compare
>> the Windows platform with e.g. C or C++, because they are languages,
>> not platforms.
>
> Getting to the pedantic/semantic part. When people say "Java is portable",
> they assume that you have a Java VM running on your platform of choice.
> Programs running inside the Java VM are portable, but whether or not Java
> is available on your Apple II is a different issue.

Then I could as well way: "When people say 'Windows apps are all
portable'", they assume that you have a Windows emulator running on
your platform of choice. Programs running inside the Windows emulator
are portable, but whether or not Windows is available on your Apple II
is a different issue".

In both cases it's the same kind of "portability".

Btw, C programs can be run on an Apple II. As a matter of fact, my very
first acquaintance with the C language I made on an Apple II, using Leor
Zolman's BDS C compiler.

>> Btw, UNIX isn't "a platform". UNIX is a collection of several similar
>> platforms which still are different enough to make some programs
>> written for e.g. Linux source incompatible with e.g. Free-BSD, HP-UX or AIX.
>
> Java is a collection of several similar platforms (Sun's, GNU classpath,
> several commercial versions, some open source versions) running similar
> goodies, but each has been limited or extended in some way.
>
> If you think of a "POSIX + gcc" platform, it's fairly similar to Java.

.....except the security aspects... :-)

You could also say: "if you think MSVC + Windows platform, it's
fairly similar to Java".

--
----------------------------------------------------------------
Paul Schlyter, Grev Turegatan 40, SE-114 38 Stockholm, SWEDEN
e-mail: pausch at stockholm dot bostream dot se
WWW: http://stjarnhimlen.se/
From: Bruce Tomlin on
In article <e56rj1$7lo$1(a)merope.saaf.se>,
pausch(a)saaf.se (Paul Schlyter) wrote:

> numbers for your number crunching stuff? Forget about Java then.... or
> does your hardware have 1-complement signed integers? Java requires
> integers to be 2-complement, i.e. you must then have some emulation layer
> on top of your native integer format - that's inefficient.

Seriously, has anyone used 1's complement arithmetic in the past 10-20
years or so? And why?
From: John B. Matthews on
In article <e56rj1$7lo$1(a)merope.saaf.se>,
pausch(a)saaf.se (Paul Schlyter) wrote:

> In article <1148544621.115246.248890(a)y43g2000cwc.googlegroups.com>,
> mdj <mdj.mdj(a)gmail.com> wrote:
[...]
> > The key concepts that are missing here are pointers, and more specifically,
> > the ability to perform arbitrary arithmetic on pointer types.
>
> FORTRAN, Pascal and Ada lacks this too.
[...]

This is certainly false for Ada:

http://www.adapower.com/rm95.php

In particular, the standard package Interfaces.C.Pointers overloads the
"+" and "-" operators for just this purpose.

http://www.adapower.com/rm95/RM-B-3-2.html

It is arguably false for many widely used flavors of Pascal including
Object Pascal and Turbo Pascal.

Even Fortran has a non-standard extension for this:

http://gcc.gnu.org/onlinedocs/gfortran/Cray-pointers.html

--
John Matthews
jmatthews at wright dot edu
www dot wright dot edu/~john.matthews/
From: mdj on

Paul Schlyter wrote:

> Java is not unique in this respect - languages like FORTRAN, C, C++,
> Pascal and Ada are also void of any language construct that would bind
> it, or any program written in it, to a specific architecture. To
> write non-portable programs in these languages you almost always have
> to use implementation specific extensions (with the exception of C and C++,
> where you can use pointes for a lot of architecture dependent stuff -- otoh
> if you read the standards of these languages carefully, the behaviour of
> such programs is described as "undefined").

I'm unfamiliar with FORTRAN, However all the other language you mention
make it possible to make use of the underlying architecture. The only
difference is that Pascal/Ada force you to be specific about your
intentions whereas C/C++ allows this to be done very simply.

> > The key concepts that are missing here are pointers, and more specifically,
> > the ability to perform arbitrary arithmetic on pointer types.
>
> FORTRAN, Pascal and Ada lacks this too.

Both Pascal and Ada allow arbitrary pointer arithmetic, granted not be
explicit language construct in the case of Pascal, but it's still
easily done, and was actually quite routinely done. I used this
facility myself many times on the Apple II when there was no provided
library routine to access a hardware feature.

> > Additionally, the language specification defines EXACTLY the size and
> > precision of each data type.
>
> ...which will limit Java to architectures having exactly these sizes and
> precisions of their data types. Do you need 128-bit binary floating-point
> numbers for your number crunching stuff? Forget about Java then.... or
> does your hardware have 1-complement signed integers? Java requires
> integers to be 2-complement, i.e. you must then have some emulation layer
> on top of your native integer format - that's inefficient.

That correct, but that's the price of portability ;-)

> > C and C++ on the other hand, not only allow arbitrary pointer arithmetic,
> > but also only define in the standard, the minimum size requirements of each
> > data type.

Yes, and this is a cause of portability issues for programs written in
those languages.

> ....which will enable you to use the underlying hardware more efficiently.
> Do you want to write a program which runs on a 64-bit machine?, and use
> the increased size of the basic data type? Forget about Java - that language
> has a 32-bit architecture more or less hardwired into it. Just like UCSD
> Pascal (which has a concept similar to Java: portable binary code which is
> to be interpreted on the target machine) had a 16-bit architecture more or less
> hardwired into it.
>
> > It is impossible to write a Java program that's bound to a specific
> > machine architecture.
>
> ...actually, it's quite easy to do that: just use some of the common Java
> class libraries in your program, then try to run it on some architecture
> except the java architecture, i.e. without a JVM ......

No. You're confusing the issues. Java is comprised of a language, an
API and a virtual machine. The API is written in Java, and is just a
portable as any other Java program.

> > With C/C++ it's easy, and common to do so. In fact, the ability of C/C++
> > to do such things is what makes it such a useful language for low level
> > programming, virtually replacing the need for assembly language, except
> > in cases of utilising the varied coprocessors that adorn modern CPU's.
>
> ....in Java, you must use JNI, and C, to do this....... :-)

Which is the entire point; non-portable code stays in the non-portable
realm. There is actually plenty of example of code that was rewritten
in Java since it turned out to be more efficient that way, because the
necessary restrictions of JNI due to portability.

> > Ever tried porting some C code to a 64 bit platform?
>
> I've ported some 8-bit and 16-bit C code to 32 bit platforms, so I'm well
> acquainted with the problems which then may arise. Porting from 32-bit
> to 64-bit is probably not much different.
>
> > Many C compilers implement int as a 32 bit quantity even on 64 bit
> > architectures,
>
> Those C compilers aren't follow ANSI C compliant, I would say.

Sure they are. The ANSI standard requires only that int is at least 16
bit, and signed. Addresses are whatever they are on the host
architecture.

> > which completely hoses an enormous amount of C code, which wrongly assumes
> > that int and int * are the same size, simply because for many years on most
> > implementations, it was.
>
> Check out:
>
> http://www.doc.ic.ac.uk/lab/secondyear/cstyle/node32.html#SECTION000260000000000000000
>
> in particular point 10, the last point.

Yes, but these are guidelines established to discipline C programmers
to write portable code! They are only necessary because the language
itself is not portable; it allows you to write a valid program that is
architecture dependant, and such guidelines are prevalent due to the
fact that people ignorant of them will write non-portable applications
without even realising it.

> > You could point out that this is terrible coding practice, and I'd
> > agree with you. It was however one of the most common optimisations you
> > could do in C, and was frequently done precisely because of the
> > performance advantage it had.
>
> I don't see the performance advantage here. In what way would it
> degrade performance to keep int's separare from pointers? At least
> the people doing this could have typedef'ed int to some name clearly
> indicating this int actually held a pointer.

Could have, didn't. That's the point.

> I know about these implementations -- but how well do these non-JVM
> Java compilers run most Java programs originally written for JVM-Java?
> They lack a number of classes in the Java class library, don't they?
> Java is, by itself, such a small language that you cannot do much
> interesting with it without using the Java class libraries.
>
> > Amusingly, there are a few higher level scripting languages out there
> > that are actually 'less portable' than java, because they provide
> > machine level access facilities that totally destroy the independence
> > of code written to use them.
>
> You can do that in Java too -- read up on JNI !!!!!

No, JNI forces architecture dependent code to be written in a language
other than Java and linked to it via very specific portably defined
C/C++ interface. You can't just link in any old thing, you have to wrap
it in the portable interface of JNI on the C/C++ side.

> >> The Java platform doesn't exist in hardware - it must be simulated
> >> in software. "But that means Java is portable: I can run my JVM on
> >> several other platforms" -- true, but if you define "portability" in
> >> such a way, then all Windows software becomes equally portable: just
> >> start your favourite Windows emulator on either your Mac or your Linux
> >> machine, and run your Windows software on it....
> >
> > I'd be interested to hear a definition of 'portable' that doesn't apply
> > to Java, platform or language. I'd be prepared to conceed that perhaps
> > Linux could be considered "more portable" as it's a 'platform' that's
> > been ported to more architectures than perhaps any other in history.
> > The fact remains though, than even with Linux, one must be very
> > cautious not to write code in a machine dependant way while using it's
> > 'natural' languages.
> >
> > The big issue that existed with Microsofts implementation of Java, was
> > that they extended the language to permit pointer manipulation and
> > direct calls to native code segments, so that you can directly call the
> > Win32 API. This enabled them to easily generate Java stubs for the
> > entire Win32 API.
>
> You can do that also in Sun's Java - just use JNI and some glue C code....

It's not at all the same thing. Linking a code section from a
non-portable language via a portable interface is a radically different
approach than modifying a portable language to include non-portable
features. This is the basis of the Sun/Microsoft dispute.

> > This compromises not only the portability of Java
> > programs, but also the security model provided by the Java platform,
> > which is dependent on programs not being able to access memory that
> > belong to the VM, or any other program that's running in the same
> > memory space.
>
> How well is that security model maintained in GNU's Java implementation
> which runs without any VM and generates native code?

Just as well, of course. The language definition is the same, and it
still prevents you writing code that will access machine dependant
features.

> Yep -- Java was about to be standardized some years ago, but then Sun
> changed its mind and stopped that. Even C# now has an (ECMA) standard.

Which is to be honest a pointless marketing exercise. The language
definition itself is useless without its API, as 99.9% of useful C#
programs rely on the .NET API, which is in itself not portable - it
relies heavily on Win32 to provide its functionality.

The Java API on the other hand, is mostly written in Java, and utilises
a very small number of host OS facilities, all of which exist on
virtually every platform. In fact, it relies on the portable subset of
other languages to define these facilities.

> Here you compare two platforms. I agree with what you say here, however
> it does illuminate my point: Java isn't platform independent, Java is
> a platform. And here you compare the Java platform with the Windows
> platform. That makes sense. It would not have made sense to compare
> the Windows platform with e.g. C or C++, because they are languages,
> not platforms.

This is true. Java is a Language, an API specification, and a VM. The
VM + API constitutes a platform. Comparing the Windows platform to the
Java platform however isn't sensible - the Windows platform is
non-portable, the Java platform is designed to be portable.

> Now even you call Java a platform....

Because it is. A language, and a platform. When you refer to Java you
have to be specific about whether you mean the Java language, or the
Java platform, generally the terms are used interchangably and it's
discernable from context what someone is referring to.

> Btw, UNIX isn't "a platform". UNIX is a collection of several similar
> platforms which still are different enough to make some programs
> written for e.g. Linux source incompatible with e.g. Free-BSD, HP-UX or AIX.

This is what the POSIX standard is for. Even Microsoft made a token
attempt at providing a POSIX interface to Windows NT. They pulled it in
the end. These days you can get this interface via Cygwin. There's a
large subset of common functionality across all of these systems which
constitute the UNIX platform. Like anything, if you rely on
vendor-specific extensions, you break portability.

I mean really, to create anything that allows sophisticated
applications to run across multiple platforms, you must specify a
'meta-platform' which hides the specifics of each specific platform.
This is exactly what Java does. Without this technique, you're forced
to write lowest common denominator code.

Considering C/C++ in this light would mean sticking with only the ANSI
standards, which wouldn't allow you to leverage any OS facility beyond
basic file I/O

Java certainly has its blemishes, but how else does one write a
sophisticated application, then pick it up, either binary or source,
and drop it on every major OS and architecture ?

Matt