putfield <field-spec> <descriptor><field-spec> is composed of two parts, a classname and a fieldname. The classname is all of the characters in the <field-spec> up to the last '/' character, and the fieldname is the rest of the characters after the last '/'. For example:
foo/baz/AnotherClass/aVeryLongFieldName -- classname -------/-- fieldname -----{{JM - can we turn this into a nicer diagram?}}
<descriptor> is the Java type descriptor for the field, for example Ljava/io/PrintStream;
In Jasmin, the .field directive is used to add a field to a class. See Chapter 16 for a description of this and other Jasmin directives.
Stack Before Before
or, for fields holding doubles or longs: After value ... objectref ...
Description After value-word1 ... value-word2 objectref ...
putfield sets the value of the field identified by <field-spec> in objectref (a reference to an object) to the single or double word value on the operand stack. For example, if you have the class:
package xyz; class Point { public int xCoord, yCoord; };Then, assuming p is an instance of the class Point, writing the Java expression:
p.xCoord = 10;generates JVM code like:
aload_1 ; push object in local varable 1 (i.e. p) onto the stack bipush 10 ; push the integer 10 onto the stack putfield xyz/Point/xCoord I ; set the value of the integer field p.xCoord to 10In Jasmin, putfield takes two parameters, <field-spec> and <descriptor>. <field-spec> provides classname, the name of the class that defines the field, as well as fieldname, the name of the field. In the example above, the <field-spec> is "xyz/Point/xCoord", indicating that the classname is called "xyz/Point" and the fieldname is "xCoord". <descriptor> indicates the type of data held in the field, and is a standard Java type descriptor (see Chapter 4). In the example above, <descriptor> is "I", since the field holds an integer.
putfield first resolves classname to a Java class. Then it locates fieldname in that class, determining the size of the field (in bytes) and its offset (in bytes) from the base of the object data. The type of the field must match <descriptor>. See Chapter 7 for a full discussion of how fields are resolved
To set the value of the field, putfield pops either a 4-byte or 8-byte quantity off the stack (depending on the field descriptor), and truncates it to be width bytes long. Then it sets the bytes starting at offset and extending for width bytes in objectref's instance data to the new value.
Exceptions
NullPointerException - objectref is null
Bytecode
In bytecode, the putfield opcode is followed by a 16-bit unsigned integer index. This is the index of an entry in the constant pool of the current class. The entry is tagged a CONSTANT_Fieldref entry. The fieldref entry lists a CONSTANT_Class entry in the constant pool whose name is the classname given in <field-spec>, as well as a CONSTANT_NameAndType entry in the constant pool, whose name is the fieldname given in <field-spec>, and whose descriptor is the string given by <descriptor>.
Type | Description |
u1 | putfield opcode = 0xB5 (181) |
u2 | index |
getfield, putstatic, getstatic
Notes
Fields cannot be overriden, although they can be 'shadowed'. For example, with the two classes:
class A { int x; } and class B extends A { int x; }instances of B will have storage for both the field "A/x" and the field "B/x". Which field is accessed is determined by the class name given in <field-spec>.