Back to home page

OSCL-LXR

 
 

    


0001 Java(tm) Binary Kernel Support for Linux v1.03
0002 ----------------------------------------------
0003 
0004 Linux beats them ALL! While all other OS's are TALKING about direct
0005 support of Java Binaries in the OS, Linux is doing it!
0006 
0007 You can execute Java applications and Java Applets just like any
0008 other program after you have done the following:
0009 
0010 1) You MUST FIRST install the Java Developers Kit for Linux.
0011    The Java on Linux HOWTO gives the details on getting and
0012    installing this. This HOWTO can be found at:
0013 
0014         ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO
0015 
0016    You should also set up a reasonable CLASSPATH environment
0017    variable to use Java applications that make use of any
0018    nonstandard classes (not included in the same directory
0019    as the application itself).
0020 
0021 2) You have to compile BINFMT_MISC either as a module or into
0022    the kernel (``CONFIG_BINFMT_MISC``) and set it up properly.
0023    If you choose to compile it as a module, you will have
0024    to insert it manually with modprobe/insmod, as kmod
0025    cannot easily be supported with binfmt_misc.
0026    Read the file 'binfmt_misc.txt' in this directory to know
0027    more about the configuration process.
0028 
0029 3) Add the following configuration items to binfmt_misc
0030    (you should really have read ``binfmt_misc.txt`` now):
0031    support for Java applications::
0032 
0033      ':Java:M::\xca\xfe\xba\xbe::/usr/local/bin/javawrapper:'
0034 
0035    support for executable Jar files::
0036 
0037      ':ExecutableJAR:E::jar::/usr/local/bin/jarwrapper:'
0038 
0039    support for Java Applets::
0040 
0041      ':Applet:E::html::/usr/bin/appletviewer:'
0042 
0043    or the following, if you want to be more selective::
0044 
0045      ':Applet:M::<!--applet::/usr/bin/appletviewer:'
0046 
0047    Of course you have to fix the path names. The path/file names given in this
0048    document match the Debian 2.1 system. (i.e. jdk installed in ``/usr``,
0049    custom wrappers from this document in ``/usr/local``)
0050 
0051    Note, that for the more selective applet support you have to modify
0052    existing html-files to contain ``<!--applet-->`` in the first line
0053    (``<`` has to be the first character!) to let this work!
0054 
0055    For the compiled Java programs you need a wrapper script like the
0056    following (this is because Java is broken in case of the filename
0057    handling), again fix the path names, both in the script and in the
0058    above given configuration string.
0059 
0060    You, too, need the little program after the script. Compile like::
0061 
0062         gcc -O2 -o javaclassname javaclassname.c
0063 
0064    and stick it to ``/usr/local/bin``.
0065 
0066    Both the javawrapper shellscript and the javaclassname program
0067    were supplied by Colin J. Watson <cjw44@cam.ac.uk>.
0068 
0069 Javawrapper shell script:
0070 
0071 .. code-block:: sh
0072 
0073   #!/bin/bash
0074   # /usr/local/bin/javawrapper - the wrapper for binfmt_misc/java
0075 
0076   if [ -z "$1" ]; then
0077         exec 1>&2
0078         echo Usage: $0 class-file
0079         exit 1
0080   fi
0081 
0082   CLASS=$1
0083   FQCLASS=`/usr/local/bin/javaclassname $1`
0084   FQCLASSN=`echo $FQCLASS | sed -e 's/^.*\.\([^.]*\)$/\1/'`
0085   FQCLASSP=`echo $FQCLASS | sed -e 's-\.-/-g' -e 's-^[^/]*$--' -e 's-/[^/]*$--'`
0086 
0087   # for example:
0088   # CLASS=Test.class
0089   # FQCLASS=foo.bar.Test
0090   # FQCLASSN=Test
0091   # FQCLASSP=foo/bar
0092 
0093   unset CLASSBASE
0094 
0095   declare -i LINKLEVEL=0
0096 
0097   while :; do
0098         if [ "`basename $CLASS .class`" == "$FQCLASSN" ]; then
0099                 # See if this directory works straight off
0100                 cd -L `dirname $CLASS`
0101                 CLASSDIR=$PWD
0102                 cd $OLDPWD
0103                 if echo $CLASSDIR | grep -q "$FQCLASSP$"; then
0104                         CLASSBASE=`echo $CLASSDIR | sed -e "s.$FQCLASSP$.."`
0105                         break;
0106                 fi
0107                 # Try dereferencing the directory name
0108                 cd -P `dirname $CLASS`
0109                 CLASSDIR=$PWD
0110                 cd $OLDPWD
0111                 if echo $CLASSDIR | grep -q "$FQCLASSP$"; then
0112                         CLASSBASE=`echo $CLASSDIR | sed -e "s.$FQCLASSP$.."`
0113                         break;
0114                 fi
0115                 # If no other possible filename exists
0116                 if [ ! -L $CLASS ]; then
0117                         exec 1>&2
0118                         echo $0:
0119                         echo "  $CLASS should be in a" \
0120                              "directory tree called $FQCLASSP"
0121                         exit 1
0122                 fi
0123         fi
0124         if [ ! -L $CLASS ]; then break; fi
0125         # Go down one more level of symbolic links
0126         let LINKLEVEL+=1
0127         if [ $LINKLEVEL -gt 5 ]; then
0128                 exec 1>&2
0129                 echo $0:
0130                 echo "  Too many symbolic links encountered"
0131                 exit 1
0132         fi
0133         CLASS=`ls --color=no -l $CLASS | sed -e 's/^.* \([^ ]*\)$/\1/'`
0134   done
0135 
0136   if [ -z "$CLASSBASE" ]; then
0137         if [ -z "$FQCLASSP" ]; then
0138                 GOODNAME=$FQCLASSN.class
0139         else
0140                 GOODNAME=$FQCLASSP/$FQCLASSN.class
0141         fi
0142         exec 1>&2
0143         echo $0:
0144         echo "  $FQCLASS should be in a file called $GOODNAME"
0145         exit 1
0146   fi
0147 
0148   if ! echo $CLASSPATH | grep -q "^\(.*:\)*$CLASSBASE\(:.*\)*"; then
0149         # class is not in CLASSPATH, so prepend dir of class to CLASSPATH
0150         if [ -z "${CLASSPATH}" ] ; then
0151                 export CLASSPATH=$CLASSBASE
0152         else
0153                 export CLASSPATH=$CLASSBASE:$CLASSPATH
0154         fi
0155   fi
0156 
0157   shift
0158   /usr/bin/java $FQCLASS "$@"
0159 
0160 javaclassname.c:
0161 
0162 .. code-block:: c
0163 
0164   /* javaclassname.c
0165    *
0166    * Extracts the class name from a Java class file; intended for use in a Java
0167    * wrapper of the type supported by the binfmt_misc option in the Linux kernel.
0168    *
0169    * Copyright (C) 1999 Colin J. Watson <cjw44@cam.ac.uk>.
0170    *
0171    * This program is free software; you can redistribute it and/or modify
0172    * it under the terms of the GNU General Public License as published by
0173    * the Free Software Foundation; either version 2 of the License, or
0174    * (at your option) any later version.
0175    *
0176    * This program is distributed in the hope that it will be useful,
0177    * but WITHOUT ANY WARRANTY; without even the implied warranty of
0178    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0179    * GNU General Public License for more details.
0180    *
0181    * You should have received a copy of the GNU General Public License
0182    * along with this program; if not, write to the Free Software
0183    * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0184    */
0185 
0186   #include <stdlib.h>
0187   #include <stdio.h>
0188   #include <stdarg.h>
0189   #include <sys/types.h>
0190 
0191   /* From Sun's Java VM Specification, as tag entries in the constant pool. */
0192 
0193   #define CP_UTF8 1
0194   #define CP_INTEGER 3
0195   #define CP_FLOAT 4
0196   #define CP_LONG 5
0197   #define CP_DOUBLE 6
0198   #define CP_CLASS 7
0199   #define CP_STRING 8
0200   #define CP_FIELDREF 9
0201   #define CP_METHODREF 10
0202   #define CP_INTERFACEMETHODREF 11
0203   #define CP_NAMEANDTYPE 12
0204   #define CP_METHODHANDLE 15
0205   #define CP_METHODTYPE 16
0206   #define CP_INVOKEDYNAMIC 18
0207 
0208   /* Define some commonly used error messages */
0209 
0210   #define seek_error() error("%s: Cannot seek\n", program)
0211   #define corrupt_error() error("%s: Class file corrupt\n", program)
0212   #define eof_error() error("%s: Unexpected end of file\n", program)
0213   #define utf8_error() error("%s: Only ASCII 1-255 supported\n", program);
0214 
0215   char *program;
0216 
0217   long *pool;
0218 
0219   u_int8_t read_8(FILE *classfile);
0220   u_int16_t read_16(FILE *classfile);
0221   void skip_constant(FILE *classfile, u_int16_t *cur);
0222   void error(const char *format, ...);
0223   int main(int argc, char **argv);
0224 
0225   /* Reads in an unsigned 8-bit integer. */
0226   u_int8_t read_8(FILE *classfile)
0227   {
0228         int b = fgetc(classfile);
0229         if(b == EOF)
0230                 eof_error();
0231         return (u_int8_t)b;
0232   }
0233 
0234   /* Reads in an unsigned 16-bit integer. */
0235   u_int16_t read_16(FILE *classfile)
0236   {
0237         int b1, b2;
0238         b1 = fgetc(classfile);
0239         if(b1 == EOF)
0240                 eof_error();
0241         b2 = fgetc(classfile);
0242         if(b2 == EOF)
0243                 eof_error();
0244         return (u_int16_t)((b1 << 8) | b2);
0245   }
0246 
0247   /* Reads in a value from the constant pool. */
0248   void skip_constant(FILE *classfile, u_int16_t *cur)
0249   {
0250         u_int16_t len;
0251         int seekerr = 1;
0252         pool[*cur] = ftell(classfile);
0253         switch(read_8(classfile))
0254         {
0255         case CP_UTF8:
0256                 len = read_16(classfile);
0257                 seekerr = fseek(classfile, len, SEEK_CUR);
0258                 break;
0259         case CP_CLASS:
0260         case CP_STRING:
0261         case CP_METHODTYPE:
0262                 seekerr = fseek(classfile, 2, SEEK_CUR);
0263                 break;
0264         case CP_METHODHANDLE:
0265                 seekerr = fseek(classfile, 3, SEEK_CUR);
0266                 break;
0267         case CP_INTEGER:
0268         case CP_FLOAT:
0269         case CP_FIELDREF:
0270         case CP_METHODREF:
0271         case CP_INTERFACEMETHODREF:
0272         case CP_NAMEANDTYPE:
0273         case CP_INVOKEDYNAMIC:
0274                 seekerr = fseek(classfile, 4, SEEK_CUR);
0275                 break;
0276         case CP_LONG:
0277         case CP_DOUBLE:
0278                 seekerr = fseek(classfile, 8, SEEK_CUR);
0279                 ++(*cur);
0280                 break;
0281         default:
0282                 corrupt_error();
0283         }
0284         if(seekerr)
0285                 seek_error();
0286   }
0287 
0288   void error(const char *format, ...)
0289   {
0290         va_list ap;
0291         va_start(ap, format);
0292         vfprintf(stderr, format, ap);
0293         va_end(ap);
0294         exit(1);
0295   }
0296 
0297   int main(int argc, char **argv)
0298   {
0299         FILE *classfile;
0300         u_int16_t cp_count, i, this_class, classinfo_ptr;
0301         u_int8_t length;
0302 
0303         program = argv[0];
0304 
0305         if(!argv[1])
0306                 error("%s: Missing input file\n", program);
0307         classfile = fopen(argv[1], "rb");
0308         if(!classfile)
0309                 error("%s: Error opening %s\n", program, argv[1]);
0310 
0311         if(fseek(classfile, 8, SEEK_SET))  /* skip magic and version numbers */
0312                 seek_error();
0313         cp_count = read_16(classfile);
0314         pool = calloc(cp_count, sizeof(long));
0315         if(!pool)
0316                 error("%s: Out of memory for constant pool\n", program);
0317 
0318         for(i = 1; i < cp_count; ++i)
0319                 skip_constant(classfile, &i);
0320         if(fseek(classfile, 2, SEEK_CUR))       /* skip access flags */
0321                 seek_error();
0322 
0323         this_class = read_16(classfile);
0324         if(this_class < 1 || this_class >= cp_count)
0325                 corrupt_error();
0326         if(!pool[this_class] || pool[this_class] == -1)
0327                 corrupt_error();
0328         if(fseek(classfile, pool[this_class] + 1, SEEK_SET))
0329                 seek_error();
0330 
0331         classinfo_ptr = read_16(classfile);
0332         if(classinfo_ptr < 1 || classinfo_ptr >= cp_count)
0333                 corrupt_error();
0334         if(!pool[classinfo_ptr] || pool[classinfo_ptr] == -1)
0335                 corrupt_error();
0336         if(fseek(classfile, pool[classinfo_ptr] + 1, SEEK_SET))
0337                 seek_error();
0338 
0339         length = read_16(classfile);
0340         for(i = 0; i < length; ++i)
0341         {
0342                 u_int8_t x = read_8(classfile);
0343                 if((x & 0x80) || !x)
0344                 {
0345                         if((x & 0xE0) == 0xC0)
0346                         {
0347                                 u_int8_t y = read_8(classfile);
0348                                 if((y & 0xC0) == 0x80)
0349                                 {
0350                                         int c = ((x & 0x1f) << 6) + (y & 0x3f);
0351                                         if(c) putchar(c);
0352                                         else utf8_error();
0353                                 }
0354                                 else utf8_error();
0355                         }
0356                         else utf8_error();
0357                 }
0358                 else if(x == '/') putchar('.');
0359                 else putchar(x);
0360         }
0361         putchar('\n');
0362         free(pool);
0363         fclose(classfile);
0364         return 0;
0365   }
0366 
0367 jarwrapper::
0368 
0369   #!/bin/bash
0370   # /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar
0371 
0372   java -jar $1
0373 
0374 
0375 Now simply ``chmod +x`` the ``.class``, ``.jar`` and/or ``.html`` files you
0376 want to execute.
0377 
0378 To add a Java program to your path best put a symbolic link to the main
0379 .class file into /usr/bin (or another place you like) omitting the .class
0380 extension. The directory containing the original .class file will be
0381 added to your CLASSPATH during execution.
0382 
0383 
0384 To test your new setup, enter in the following simple Java app, and name
0385 it "HelloWorld.java":
0386 
0387 .. code-block:: java
0388 
0389         class HelloWorld {
0390                 public static void main(String args[]) {
0391                         System.out.println("Hello World!");
0392                 }
0393         }
0394 
0395 Now compile the application with::
0396 
0397         javac HelloWorld.java
0398 
0399 Set the executable permissions of the binary file, with::
0400 
0401         chmod 755 HelloWorld.class
0402 
0403 And then execute it::
0404 
0405         ./HelloWorld.class
0406 
0407 
0408 To execute Java Jar files, simple chmod the ``*.jar`` files to include
0409 the execution bit, then just do::
0410 
0411        ./Application.jar
0412 
0413 
0414 To execute Java Applets, simple chmod the ``*.html`` files to include
0415 the execution bit, then just do::
0416 
0417         ./Applet.html
0418 
0419 
0420 originally by Brian A. Lantz, brian@lantz.com
0421 heavily edited for binfmt_misc by Richard Günther
0422 new scripts by Colin J. Watson <cjw44@cam.ac.uk>
0423 added executable Jar file support by Kurt Huwig <kurt@iku-netz.de>