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>