Bug 7066

Summary: gcj does not have a way to generate 1.1 bytecode
Product: gcc Reporter: Bruno Haible <bruno>
Component: javaAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: enhancement CC: bruno, gcc-bugs, java-prs, tromey
Priority: P3    
Version: 3.1   
Target Milestone: 4.3.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2005-07-15 21:32:57
Bug Depends on: 28067    
Bug Blocks:    

Description Bruno Haible 2002-06-18 06:16:02 UTC
gcj 3.1 generates invalid bytecode for the following program.

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D GetURL.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
import java.io.*;
import java.net.*;

public class GetURL {
  private static long timeout =3D 30*1000;
  private boolean done;
  private Thread timeoutThread;
  public void fetch (String s) {
    URL url;
    try {
      url =3D new URL(s);
    } catch (MalformedURLException e) {
      System.exit(1);
      return;
    }
    System.err.print("Retrieving "+s+"...");
    System.err.flush();
    done =3D false;
    timeoutThread =3D
      new Thread() {
        public void run () {
          try {
            sleep(timeout);
            if (!done) {
              System.err.println(" timed out.");
              System.exit(1);
            }
          } catch (InterruptedException e) {
          }
        }
      };
    timeoutThread.start();
    try {
      InputStream istream =3D new BufferedInputStream(url.openStream())=
;
      OutputStream ostream =3D new BufferedOutputStream(System.out);
      for (;;) {
        int b =3D istream.read();
        if (b < 0) break;
        ostream.write(b);
      }
      ostream.close();
      System.out.flush();
      istream.close();
    } catch (IOException e) {
      System.err.println(" failed.");
      System.exit(1);
    }
    done =3D true;
    System.err.println(" done.");
  }
  public static void main (String[] args) {
    if (args.length !=3D 1)
      System.exit(1);
    (new GetURL()).fetch(args[0]);
    System.exit(0);
  }
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D

Release:
3.1

Environment:
System: Linux linuix 2.4.18-4GB #1 Wed Mar 27 13:57:05 UTC 2002 i686 un=
known
Architecture: i686

       =20
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: /packages2/gcc-3.1/configure --prefix=3D/packages/gnu-=
snapshot --enable-shared --enable-version-specific-runtime-libs --enabl=
e-nls

How-To-Repeat:

Save the above snippet as GetURL.java. Then
$ gcj --version
gcj (GCC) 3.1
Copyright =A9 2002 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.  =
Il n'y a PAS
GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

$ gcj -C -d . GetURL.java=20

$ someurl=3D"http://localhost/" # or some other accessible URL

$ gij --version
gij (GNU libgcj) version 3.1

Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is=
 NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURP=
OSE.

$ CLASSPATH=3D. gij GetURL $someurl
Retrieving http://localhost/...Exception in thread "main" java.lang.Int=
ernalError: Thread.start called but threads not available
   at 0x4025f270: java.lang.Throwable.Throwable(java.lang.String) (/pac=
kages/gnu-snapshot/lib/libgcj.so.3)
   at 0x4024dcf6: java.lang.Error.Error(java.lang.String) (/packages/gn=
u-snapshot/lib/libgcj.so.3)
   at 0x4025f606: java.lang.VirtualMachineError.VirtualMachineError(jav=
a.lang.String) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x4024ff06: java.lang.InternalError.InternalError(java.lang.Strin=
g) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x403cc038: _Jv_ThreadStart(java.lang.Thread, int, void ()(java.l=
ang.Thread)) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x40240aa1: java.lang.Thread.start() (/packages/gnu-snapshot/lib/=
libgcj.so.3)
   at 0x403db0f7: ffi_call_SYSV (/packages/gnu-snapshot/lib/libgcj.so.3=
)
   at 0x403db0a7: ffi_raw_call (/packages/gnu-snapshot/lib/libgcj.so.3)=

   at 0x40231048: _Jv_InterpMethod.continue1(_Jv_InterpMethodInvocation=
) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x403e60a4: _Jv_InterpMethod.run(ffi_cif, void, ffi_raw, _Jv_Inte=
rpMethodInvocation) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x4022ee14: _Jv_InterpMethod.run_normal(ffi_cif, void, ffi_raw, v=
oid) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x403daf5c: ?? (??:0)
   at 0x403db0f7: ffi_call_SYSV (/packages/gnu-snapshot/lib/libgcj.so.3=
)
   at 0x403db0a7: ffi_raw_call (/packages/gnu-snapshot/lib/libgcj.so.3)=

   at 0x40231048: _Jv_InterpMethod.continue1(_Jv_InterpMethodInvocation=
) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x403e60a4: _Jv_InterpMethod.run(ffi_cif, void, ffi_raw, _Jv_Inte=
rpMethodInvocation) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x4022ee14: _Jv_InterpMethod.run_normal(ffi_cif, void, ffi_raw, v=
oid) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x403daf5c: ?? (??:0)
   at 0x40235258: gnu.gcj.runtime.FirstThread.call_main() (/packages/gn=
u-snapshot/lib/libgcj.so.3)
   at 0x402bde78: gnu.gcj.runtime.FirstThread.run() (/packages/gnu-snap=
shot/lib/libgcj.so.3)
   at 0x40240a0c: _Jv_ThreadRun(java.lang.Thread) (/packages/gnu-snapsh=
ot/lib/libgcj.so.3)
   at 0x4021d094: _Jv_RunMain(java.lang.Class, byte const, int, byte co=
nst, boolean) (/packages/gnu-snapshot/lib/libgcj.so.3)
   at 0x08048a40: main (/packages2/gcc-3.1/libjava/gij.cc:140)
   at 0x405e3668: __libc_start_main (/lib/libc.so.6)
   at 0x080487a1: _start (??:0)

$ java -version
java version "1.3.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_02-b02)
Java HotSpot(TM) Client VM (build 1.3.1_02-b02, mixed mode)

$ CLASSPATH=3D. java GetURL $someurl
Retrieving http://localhost/...Exception in thread "main" java.lang.Ver=
ifyError: (class: GetURL$1, method: <init> signature: (LGetURL;)V) Expe=
cting to find object/array on stack
        at GetURL.fetch(GetURL.java:31)
        at GetURL.main(GetURL.java:54)

$ javap -c 'GetURL$1'
Compiled from GetURL.java
final class GetURL$1 extends java.lang.Thread {
    GetURL$1(GetURL);
    public void run();
}

Method GetURL$1(GetURL)
   0 aload_0
   1 aload_1
   2 putfield #12 <Field GetURL this$0>
   5 aload_0
   6 invokespecial #15 <Method java.lang.Thread()>
   9 return

...
Comment 1 Bruno Haible 2002-06-18 06:16:02 UTC
Fix:

Fix the code generated for the constructor of the anonymous inner class=

'GetURL$1'.
Comment 2 Tom Tromey 2002-06-18 09:12:43 UTC
From: Tom Tromey <tromey@redhat.com>
To: Bruno Haible <bruno@clisp.org>
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/7066: gcj generates invalid bytecode for inner classes
Date: 18 Jun 2002 09:12:43 -0600

 >>>>> "Bruno" == Bruno Haible <bruno@clisp.org> writes:
 
 Bruno> $ CLASSPATH=3D. gij GetURL $someurl
 Bruno> Retrieving http://localhost/...Exception in thread "main" java.lang.Int=
 Bruno> ernalError: Thread.start called but threads not available
 
 This means you didn't configure with --enable-threads, but your
 program uses threads.
 
 Bruno> $ java -version
 Bruno> java version "1.3.1_02"
 
 This is part of the problem...
 
 Bruno> Method GetURL$1(GetURL)
 Bruno>    0 aload_0
 Bruno>    1 aload_1
 Bruno>    2 putfield #12 <Field GetURL this$0>
 Bruno>    5 aload_0
 Bruno>    6 invokespecial #15 <Method java.lang.Thread()>
 Bruno>    9 return
 
 This is valid bytecode according to the 1.4 spec.  The 1.3 JDK doesn't
 like it though; they added a special exception to the verifier to let
 code like this through.  If you use the 1.4 "javac" you'll also see
 this.
 
 There was some discussion of this issue on the java list recently.
 Apparently the 1.4 javac is capable of generating 1.3-compatible
 bytecode, though the result can fail in some situations.  Eric
 explained it in detail.
 
 Tom

Comment 3 Tom Tromey 2002-06-18 15:23:03 UTC
From: Tom Tromey <tromey@redhat.com>
To: Bruno Haible <bruno@clisp.org>
Cc: gcc-gnats@gcc.gnu.org, Per Bothner <bothner@bothner.com>
Subject: Re: java/7066: gcj generates invalid bytecode for inner classes
Date: 18 Jun 2002 15:23:03 -0600

 Bruno> Thanks for the explanation. Is there a command line option for
 Bruno> gcj to produce Java 1.1 compliant class files? I mean, without
 Bruno> such an option, "gcj -C" is useless for me.
 
 There's no such option at this time.
 
 Per mentioned perhaps looking into this particular issue.
 
 I personally don't plan to in the forseeable future, sorry.
 It might be relatively easy to implement by hacking parse.y to
 put the field initialization after the superclass constructor call.
 (Plus adding a new command-line option, but that is easy.)
 
 Tom
Comment 4 Bruno Haible 2002-06-18 18:23:56 UTC
From: Bruno Haible <bruno@clisp.org>
To: tromey@redhat.com
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/7066: gcj generates invalid bytecode for inner classes
Date: Tue, 18 Jun 2002 18:23:56 +0200 (CEST)

 Tom Tromey writes:
 
 > This means you didn't configure with --enable-threads, but your
 > program uses threads.
 
 I see. Thanks.
 
 > Bruno> $ java -version
 > Bruno> java version "1.3.1_02"
 > 
 > This is part of the problem...
 > 
 > Bruno> Method GetURL$1(GetURL)
 > Bruno>    0 aload_0
 > Bruno>    1 aload_1
 > Bruno>    2 putfield #12 <Field GetURL this$0>
 > Bruno>    5 aload_0
 > Bruno>    6 invokespecial #15 <Method java.lang.Thread()>
 > Bruno>    9 return
 > 
 > This is valid bytecode according to the 1.4 spec.  The 1.3 JDK doesn't
 > like it though; they added a special exception to the verifier to let
 > code like this through.  If you use the 1.4 "javac" you'll also see
 > this.
 
 Thanks for the explanation. Is there a command line option for gcj to
 produce Java 1.1 compliant class files? I mean, without such an
 option, "gcj -C" is useless for me. I wanted to bytecompile Java
 sources to jars and distribute them as jar files, to be executed by
 any JDK 1.1 compliant JVM.
 
 Bruno

Comment 5 Dara Hazeghi 2003-05-27 06:20:06 UTC
Hello,

what's the status of this report. Is this problem still present? Is it in fact a bug? Thanks,

Dara
Comment 6 Bruno Haible 2003-05-27 11:28:56 UTC
Subject: Re:  gcj generates invalid bytecode for an inner class

dhazeghi@yahoo.com writes:
> PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7066
> 
> 
> 
> ------- Additional Comments From dhazeghi@yahoo.com  2003-05-27 06:20 -------
> Hello,
> 
> what's the status of this report. Is this problem still present? Is it in fact a bug? Thanks,

I consider it a bug since "gcj -C" is useless for me if it cannot
create portable bytecode.

Tom Tromey said:

  There's no such option at this time.

  Per mentioned perhaps looking into this particular issue.

  I personally don't plan to in the forseeable future, sorry.

And since I don't see any such option listed in
http://gcc.gnu.org/onlinedocs/gcc-3.3/gcj/Code-Generation.html#Code%20Generation
I assume nothing has been done on it, and the bug is still open.

Bruno
Comment 7 Andrew Pinski 2003-05-27 15:02:38 UTC
I am changing the summary based on what this bug really is.
A flag to do this would be very nice but since Java 1.1 is getting old,
I would suspect that this bug would not get fixed at all.
Comment 8 Andrew Pinski 2003-06-17 01:18:13 UTC
This an enhancement because it was never documented for gcj which version of 
bytecode that it generates.
Comment 9 Tom Tromey 2007-01-09 20:44:01 UTC
All gcj front end bugs have been fixed by the gcj-eclipse branch merge.
I'm mass-closing the affected PRs.
If you believe one of these was closed in error, please reopen it
with a note explaining why.
Thanks.