9.4 Fields and Methods

The next four bytes describe the number of fields and methods in the class:

 000163 0000           0 fields 000165 0002           2 methods 

This class has no fields and two methods. Fields and methods have identical formats. This class has no fields, so the next bytes form the definition of the first method.

                       Method 0: 000167 0009           access flags = 9 000169 001a           name = #26<main> 00016b 001b           descriptor = #27<([Ljava/lang/String;)V> 

A field or method starts off with two bytes of access flags. The meaning of these bits, from right to left, is shown in Figure 9.2 and Table 9.4.

Figure 9.2. Method access flags with value 9


The main method is both public and static, so bits 1 and 4 are set. This yields the value 9, which is the value of the access flags field. Following the access flags are two two-byte constant pool references, giving the name of the field or method (main) and the type descriptor (([Ljava/lang/String;)V). The type descriptor says that this is a method that takes an array of Strings and returns void.

Table 9.4. Method access flags
Bit Name Meaning
1 ACC_PUBLIC The field/method is public
2 ACC_PRIVATE The field/method is private
3 ACC_PROTECTED The field/method is protected
4 ACC_STATIC The field/method is static
5 ACC_FINAL The field/method is final
6 ACC_SYNCHRONIZED The method is synchronized
7 ACC_VOLATILE The field is volatile
8 ACC_TRANSIENT The field is transient
9 ACC_NATIVE The method is native
10   unused
11   unused
12 ACC_ABSTRACT The method is abstract

After the general method or field information, the file contains a list of attributes. Field and method definitions have identical formats, giving the name, type, and access information, followed by a list of attributes. Fields and methods have different kinds of attributes. Methods usually have a single attribute giving the implementation of the method. Most fields don't have any attributes at all. Only the ConstantValue attribute is defined for fields, which specifies the initial value of some fields. ConstantValue is discussed in section 9.6.1.

The attribute for this method begins

 00016d 0001              1 method attributes:                            method attribute 0 00016f 0015                name = #21<Code> 000171 00000025            length = 37 

Every attribute begins with two pieces of information: a constant pool entry indicating the name of the attribute as a UTF8 constant and four bytes indicating the length of the attribute data. The data follow. In this case, the name of the attribute is Code, and the Code attribute takes up the next 37 bytes of the file.

The name of the attribute may be anything you can fit into a UTF8 constant. The Java Virtual Machine Specification defines the name and data structure of some attributes, such as the Code attribute shown here. A JVM implementation ignores any attributes it does not recognize.

The next 37 bytes form the value of the Code attribute. They begin with some information about the resources the method requires to run:

 000175 0002               max stack: 2 000177 0001               max locals: 1 

This information indicates the maximum height of the stack and the maximum number of local variables permitted in the method. These let the program know how much space to allocate when the method is run. Since these are 16-bit numbers, the stack is limited to 65,536 slots and 65,536 local variables. Fortunately, real programs never require this much space.

This information is checked during the verification process, and if the program attempts to use more stack space or more local variables than requested here, then the class will be rejected before it gets a chance to run. For more information on how this is determined, see chapter 6.

After the method information, the class file includes the actual code for the method.

 000179 00000009           code length: 9 00017d b20006             0000 getstatic #6 000180 1201               0003 ldc #1 000182 b60007             0005 invokevirtual #7 000185 b1                 0008 return 

The first four bytes indicate that the code is nine bytes long. Since this is a four-byte number, the code may be up to four gigabytes long. However, other limitations limit practical code size to 64 kilobytes.

The next nine bytes are interpreted as Java virtual machine instructions, or bytecodes. The rightmost column of the DumpClass output gives the address of the code relative to the beginning of the code, followed by the instruction at that address.

An instruction consists of a single-byte opcode and a few bytes of arguments. The opcode determines how many bytes are used as arguments for the instruction. The next instruction begins immediately after the arguments for this instruction.

Some instructions have no arguments, like the return instruction at offset 185. Others, like the getstatic instruction at location 17d, use two bytes to represent a constant in the constant pool. The getstatic instruction at 17d points to constant 6, a Fieldref constant.

The ldc instruction at location 180 is a little unusual. Its argument is only one byte wide, but it's still interpreted as a constant reference. This constant must be an Integer, Float, or String constant.

There are two forms of the ldc instruction: ldc and ldc_w. The former requires one argument byte, which is interpreted as a reference to a constant between 0 and 255. The latter uses two bytes for its argument and may refer to any constant. In either case the constant pool entry must be a Integer, Float, Double, Long, or String entry.

The ldc instruction is provided because it requires less space in the class file. The constant entries are usually placed in the lowest values of the constant pool so that the ldc instruction can be used instead of ldc_w.

Rewriting all the constants in Oolong form, the code for the method is

 getstatic java/lang/System/out Ljava/io/PrintStream; ldc "Hello, world" invokevirtual java/io/PrintStream/println (Ljava/lang/String;)V return 

This is the same code we've seen elsewhere in the book to write the Hello, world program in Oolong. The first instruction fetches the value of out, which is a PrintStream used for writing output to the console. The second instruction loads the constant "Hello, world", which is to be printed. The third instruction invokes the println method on out, passing it "Hello, world" as an argument. The final instruction terminates the method.

 000186 0000           0 exception table entries: 

Following the bytecodes is an exception table, which begins with a two-byte count of the number of exception table entries. These entries determine how exceptions are handled when they are raised during the execution of this method. This method doesn't catch any exceptions, so the length of the table is 0.

Following the exception handler table, the code attribute may have attributes of its own. The attributes follow the same format as before: name, length, and a collection of bytes. Code attributes are used to store information about the code itself, such as debugging information. The main method has one attribute, a LineNumberTable:

 000188 0001           1 code attributes:                       code attribute 0: 00018a 0011               name = #17<LineNumberTable> 00018c 0000000a           length = 10                           Line number table: 000190 0002               length = 2 000192 0000                   start pc: 0 000194 0005                   line number: 5 000196 0008                   start pc: 8 000198 0003                   line number: 3 

This line number table has two entries in it, as indicated by the 0x0002 at byte 0x0190. Each entry maps a location in the bytecodes (called the start pc) to a line in the file (called the line number). The start pc and the line number are each given as a two-byte number, which tends to limit Java source files to 65,536 lines and the bytecode to 65,536 bytes.

The first entry maps the beginning of the method (at location 0) to line 5 of the source, which is the line containing the println. The second entry is for the return instruction at location 8. Since there is no explicit return in the source code, the compiler maps the return instruction to the first line of the method, on source line 3.

Instructions that don't have explicit mappings are assumed to be on the same line as the previous instruction in the file. Since the instructions at 3 and 5 aren't explicitly mapped, they're all assumed to be part of the source line 5, since that's where 0 is mapped to. This is reasonable, since they're all part of the println statement on line 5.

That's all there is to the main method of this program. However, the class file indicated that there was another method. Besides, there are still some bytes left in the file. Any file that ends prematurely or that has junk bytes at the end is rejected by the verification algorithm.

                           Method 1: 00019a 0000                  access flags = 0 00019c 001c                  name = #28<<init>> 00019e 001f                  descriptor = #31<()V> 

The method is named <init>; it's the constructor for the hello class. Since no constructor was given in the Java source, the Java compiler added this method automatically. This is what Dumpclass prints for <init>:

 0001a0 0001           1 method attributes:                       method attribute 0 0001a2 0015               name = #21<Code> 0001a4 0000001d           length = 29 0001a8 0001               max stack: 1 0001aa 0001               max locals: 1 0001ac 00000005           code length: 5 0001b0 2a                 00000000 aload_0 0001b1 b70008             00000001 invokespecial #8 0001b4 b1                 00000004 return 0001b5 0000               0 exception table entries: 0001b7 0001               1 code attributes:                           code attribute 0: 0001b9 0011                   name = #17<LineNumberTable> 0001bb 00000006               length = 6                               Line number table: 0001bf 0001                   length = 1 0001c1 0000                       start pc: 0 0001c3 0001                       line number: 1 

Like the main method, the <init> method has exactly one attribute: its Code attribute. It promises to push at most one thing at a time onto the stack and uses only one local variable.

The code for this method is equivalent to the Oolong:

 aload_0 invokespecial java/lang/Object/<init> ()V return 

This code invokes the superclass constructor on the object, which is the argument in local variable 0. If this method were not provided, it would not be possible to create an instance of the hello object, since an object must be constructed before it can be used. The verification algorithm requires that each constructor call a superclass constructor to ensure that objects are always completely initialized.

Like the main method, <init> also has an attribute that contains a table of line numbers. It's a little odd that there can be a line number table for a method that doesn't have any source code, but the compiler adds it anyway for the benefit of debuggers. All the instructions are mapped to the beginning of the class on line 1.

Programming for the Java Virtual Machine
Programming for the Javaв„ў Virtual Machine
ISBN: 0201309726
EAN: 2147483647
Year: 1998
Pages: 158
Authors: Joshua Engel

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net