MethodHandleItem.java revision 766a678339e615d7e0b3935111392b7eef50df24
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.dx.dex.file;
17
18import com.android.dx.rop.cst.Constant;
19import com.android.dx.rop.cst.CstBaseMethodRef;
20import com.android.dx.rop.cst.CstFieldRef;
21import com.android.dx.rop.cst.CstInterfaceMethodRef;
22import com.android.dx.rop.cst.CstMethodHandle;
23import com.android.dx.util.AnnotatedOutput;
24import com.android.dx.util.Hex;
25
26/**
27 * Representation of a method handle in a DEX file.
28 */
29public final class MethodHandleItem extends IndexedItem {
30
31    /** The item size when placed in a DEX file. */
32    private final int ITEM_SIZE = 8;
33
34    /** {@code non-null;} The method handle represented by this item. */
35    private final CstMethodHandle methodHandle;
36
37    /**
38     * Constructs an instance.
39     *
40     * @param methodHandle {@code non-null;} The method handle to represent in the DEX file.
41     */
42    public MethodHandleItem(CstMethodHandle methodHandle) {
43        this.methodHandle = methodHandle;
44    }
45
46    /** {@inheritDoc} */
47    @Override
48    public ItemType itemType() {
49        return ItemType.TYPE_METHOD_HANDLE_ITEM;
50    }
51
52    /** {@inheritDoc} */
53    @Override
54    public int writeSize() {
55        return ITEM_SIZE;
56    }
57
58    /** {@inheritDoc} */
59    @Override
60    public void addContents(DexFile file) {
61        MethodHandlesSection methodHandles = file.getMethodHandles();
62        methodHandles.intern(methodHandle);
63    }
64
65    /** {@inheritDoc} */
66    @Override
67    public void writeTo(DexFile file, AnnotatedOutput out) {
68        int targetIndex = getTargetIndex(file);
69        if (out.annotates()) {
70            out.annotate(2, "kind: " + Hex.u2(methodHandle.getMethodHandleType()));
71            out.annotate(2, "reserved:" + Hex.u2(0));
72            if (methodHandle.isAccessor()) {
73                out.annotate(2, "fieldId: " + targetIndex);
74            } else {
75                out.annotate(2, "methodId: " + targetIndex);
76            }
77            out.annotate(2, "reserved:" + Hex.u2(0));
78        }
79        out.writeShort(methodHandle.getMethodHandleType());
80        out.writeShort(0);
81        out.writeShort(getTargetIndex(file));
82        out.writeShort(0);
83    }
84
85    private int getTargetIndex(DexFile file) {
86        Constant ref = methodHandle.getRef();
87        if (methodHandle.isAccessor()) {
88            FieldIdsSection fieldIds = file.getFieldIds();
89            return fieldIds.indexOf((CstFieldRef) ref);
90        } else if (methodHandle.isInvocation()) {
91            if (ref instanceof CstInterfaceMethodRef) {
92                ref = ((CstInterfaceMethodRef)ref).toMethodRef();
93            }
94            MethodIdsSection methodIds = file.getMethodIds();
95            return methodIds.indexOf((CstBaseMethodRef) ref);
96        } else {
97            throw new IllegalStateException("Unhandled invocation type");
98        }
99    }
100}
101