@@ -33,10 +33,9 @@ <h2>Why Verify?</h2>
3333 error cases because the verifier guarantees that they are impossible.
3434 Also, we can optimize the DEX file more aggressively if we start
3535 with a stronger set of assumptions about the bytecode.
36- < li > "Exact" GC. The work peformed during verification has significant
37- overlap with the work required to compute register use maps for exact
38- GC. Improper register use, caught by the verifier, could lead to
39- subtle problems with an "exact" GC.
36+ < li > "Precise" GC. The work peformed during verification has significant
37+ overlap with the work required to compute register use maps for
38+ type-precise GC.
4039 < li > Intra-application security. If an app wants to download bits
4140 of interpreted code over the network and execute them, it can safely
4241 do so using well-established security mechanisms.
@@ -84,6 +83,12 @@ <h2>Verifier Differences</h2>
8483 or < code > filled-new-array</ code > instruction.
8584</ ul >
8685
86+ < p >
87+ The VM is permitted but not required to enforce "structured locking"
88+ constraints, which are designed to ensure that, when a method returns, all
89+ monitors locked by the method have been unlocked an equal number of times.
90+ This is not currently implemented.
91+
8792< p >
8893The Dalvik verifier is more restrictive than other VMs in one area:
8994type safety on sub-32-bit integer widths. These additional restrictions
@@ -94,24 +99,31 @@ <h2>Verifier Differences</h2>
9499< h2 > Verification Failures</ h2 >
95100
96101< p >
97- When the verifier rejects a class, it always throws a VerifyError.
98- This is different in some cases from other implementations . For example,
99- if a class attempts to perform an illegal access on a field, the expected
100- behavior is to receive an IllegalAccessError at runtime the first time
101- the field is actually accessed. The Dalvik verifier will reject the
102- entire class immediately.
102+ The verifier may reject a class immediately, or it may defer throwing
103+ an exception until the code is actually used . For example, if a class
104+ attempts to perform an illegal access on a field, the VM should throw
105+ an IllegalAccessError the first time the instruction is encountered.
106+ On the other hand, if a class contains an invalid bytecode, it should be
107+ rejected immediately with a VerifyError .
103108
104109< p >
105- It's difficult to throw the error on first use in Dalvik. Possible ways
106- to implement this behavior include:
110+ Immediate VerifyErrors are accompanied by detailed, if somewhat cryptic,
111+ information in the log file. From this it's possible to determine the
112+ exact instruction that failed, and the reason for the failure.
113+
114+ < p >
115+ It's a bit tricky to implement deferred verification errors in Dalvik.
116+ A few approaches were considered:
107117
108118< ol >
109119< li > We could replace the invalid field access instruction with a special
110120instruction that generates an illegal access error, and allow class
111121verification to complete successfully. This type of verification must
112- often be deferred to first class load, rather than be performed ahead of time
113- during DEX optimization, which means the bytecode instructions will be
114- mapped read-only during verification. So this won't work.
122+ be deferred to first class load, rather than be performed ahead of time
123+ during DEX optimization, because some failures will depend on the current
124+ execution environment (e.g. not all classes are available at dexopt time).
125+ At that point the bytecode instructions are mapped read-only during
126+ verification, so rewriting them isn't possible.
115127</ li >
116128
117129< li > We can perform the access checks when the field/method/class is
@@ -120,7 +132,7 @@ <h2>Verification Failures</h2>
120132files combine multiple classfiles together, merging the field/method/class
121133resolution results into a single large table. Once one class successfully
122134resolves the field, every other class in the same DEX file would be able
123- to access the field. This is bad .
135+ to access the field. This is incorrect .
124136</ li >
125137
126138< li > Perform the access checks on every field/method/class access.
@@ -134,25 +146,29 @@ <h2>Verification Failures</h2>
134146</ ol >
135147
136148< p >
137- Other implementations are possible, but they all involve allocating
138- some amount of additional memory or spending additional cycles
139- on non-DEX-optimized instructions. We don't want to throw an
140- IllegalAccessError at verification time, since that would indicate that
141- access to the class being verified was illegal.
149+ In early versions of Dalvik (as shipped with Android 1.0/1.5), the verifier
150+ simply regarded all problems as immediately fatal. This generally worked,
151+ but in some cases the VM was rejecting classes because of bits of code
152+ that were never used. The VerifyError itself was sometimes difficult to
153+ decipher, because it was thrown during verification rather than at the
154+ point where the problem was first noticed during execution.
142155< p >
143- One approach that might be worth pursuing: for situations like illegal
144- accesses, the verifier makes an in-RAM private copy of the method, and
145- alters the instructions there. The class object is altered to point at
146- the new copy of the instructions. This requires minimal memory overhead
147- and provides a better experience for developers.
156+ The current version uses a variation of approach #1. The dexopt
157+ command works the way it did before, leaving the code untouched and
158+ flagging fully-correct classes as "pre-verified". When the VM loads a
159+ class that didn't pass pre-verification, the verifier is invoked. If a
160+ "deferrable" problem is detected, a modifiable copy of the instructions
161+ in the problematic method is made. In that copy, the troubled instruction
162+ is replaced with an "always throw" opcode, and verification continues.
148163
149164< p >
150- The VerifyError is accompanied by detailed, if somewhat cryptic,
151- information in the log file. From this it's possible to determine the
152- exact instruction that failed, and the reason for the failure. We can
153- also constructor the VerifyError with an IllegalAccessError passed in as
154- the cause .
165+ In the example used earlier, an attempt to read from an inaccessible
166+ field would result in the "field get" instruction being replaced by
167+ "always throw IllegalAccessError on field X". Creating copies of method
168+ bodies requires additional heap space, but since this affects very few
169+ methods overall the memory impact should be minor .
155170
171+ < p >
156172< address > Copyright © 2008 The Android Open Source Project</ address >
157173
158174</ body >
0 commit comments