This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 253549
Collapse All | Expand All

(-)a/src/share/classes/com/sun/tools/hc/LambdaMetafactory.java (+190 lines)
Line 0 Link Here
1
package com.sun.tools.hc;
2
3
import java.io.UnsupportedEncodingException;
4
import java.lang.invoke.CallSite;
5
import java.lang.invoke.LambdaConversionException;
6
import java.lang.invoke.MethodHandle;
7
import java.lang.invoke.MethodHandles;
8
import java.lang.invoke.MethodType;
9
import java.lang.reflect.Array;
10
import java.lang.reflect.Field;
11
import java.lang.reflect.Method;
12
import java.util.logging.Logger;
13
14
15
16
/**
17
 *
18
 * @author Tomas Zezula
19
 */
20
public class LambdaMetafactory {
21
22
    public static final int FLAG_SERIALIZABLE = 1 << 0;
23
    public static final int FLAG_MARKERS = 1 << 1;
24
    public static final int FLAG_BRIDGES = 1 << 2;
25
26
    private static final Logger LOG = Logger.getLogger(LambdaMetafactory.class.getName());
27
    private static final byte[] PATTERN;
28
    private static final byte[] REPLACE;
29
    static {
30
        try {
31
            PATTERN = "java/lang/invoke/LambdaMetafactory".getBytes("UTF-8"); //NOI18N
32
            REPLACE = "com/sun/tools/hc/LambdaMetafactory".getBytes("UTF-8"); //NOI18N
33
        } catch (UnsupportedEncodingException e) {
34
            throw new RuntimeException(e);
35
        }
36
    }
37
    private static final Method mm;
38
    private static final Method am;
39
    private static final ReflectiveOperationException refOpEx;
40
    static {
41
        Method mfm = null;
42
        Method amm = null;
43
        ReflectiveOperationException roe = null;
44
        try {
45
            final Class<?> clz = Class.forName("java.lang.invoke.LambdaMetafactory"); //NOI18N
46
            mfm = clz.getMethod(
47
                    "metafactory",  //NOI18N
48
                    MethodHandles.Lookup.class,
49
                    String.class,
50
                    MethodType.class,
51
                    MethodType.class,
52
                    MethodHandle.class,
53
                    MethodType.class);
54
            amm = clz.getMethod(
55
                    "altMetafactory",   //NOI18N
56
                    MethodHandles.Lookup.class,
57
                    String.class,
58
                    MethodType.class,
59
                    new Object[0].getClass());
60
        } catch (ReflectiveOperationException e) {
61
            roe = e;
62
        }
63
        mm = mfm;
64
        am = amm;
65
        refOpEx = roe;
66
    }
67
68
    public static CallSite metafactory(MethodHandles.Lookup caller,
69
                                       String invokedName,
70
                                       MethodType invokedType,
71
                                       MethodType samMethodType,
72
                                       MethodHandle implMethod,
73
                                       MethodType instantiatedMethodType) throws LambdaConversionException {
74
        if (mm != null) {
75
            try {
76
                return (CallSite) mm.invoke(
77
                        null,
78
                        caller,
79
                        invokedName,
80
                        translate(invokedType),
81
                        samMethodType,
82
                        implMethod,
83
                        instantiatedMethodType);
84
            } catch (ReflectiveOperationException e) {
85
                throw new RuntimeException(e);
86
            }
87
        } else {
88
            throw new RuntimeException(refOpEx);
89
        }
90
    }
91
92
    public static CallSite altMetafactory(MethodHandles.Lookup caller,
93
                                          String invokedName,
94
                                          MethodType invokedType,
95
                                          Object... args) throws LambdaConversionException {
96
        if (am != null) {
97
            try {
98
                return (CallSite) am.invoke(
99
                    null,
100
                    caller,
101
                    invokedName,
102
                    translate(invokedType),
103
                    args);
104
            } catch (ReflectiveOperationException e) {
105
                throw new RuntimeException(e);
106
            }
107
        } else {
108
            throw new RuntimeException(refOpEx);
109
        }
110
    }
111
112
    public static byte[] translateClassFile(
113
            final byte[] data,
114
            final int start,
115
            final int end) {
116
        for (int index = find(data,start,end,PATTERN);
117
             index >= 0;
118
             index = find(data,index+PATTERN.length, end, PATTERN)) {
119
            System.arraycopy(REPLACE, 0, data, index, REPLACE.length);
120
        }
121
        return data;
122
    }
123
124
    private static int find(
125
        final byte[] data,
126
        final int start,
127
        final int end,
128
        final byte[] pattern)  {
129
        int i = start;
130
        int j = 0;
131
        for (; i < end && j < pattern.length; i++) {
132
            if (data[i] == pattern[j]) {
133
                j++;
134
            } else {
135
                j=0;
136
            }
137
        }
138
        return j == pattern.length ?
139
            i - j :
140
            -1;
141
    }
142
143
    private static MethodType translate(MethodType mt) {
144
        final Class<?> origRtype = mt.returnType();
145
        final Class<?> rtype = translate(origRtype);
146
        final boolean changeRtype = origRtype != rtype;
147
        boolean changePtypes = false;
148
        final Class<?>[] ptypes = new Class<?>[mt.parameterCount()];
149
        for (int i = 0; i < ptypes.length; i++) {
150
            final Class<?> origPtype = mt.parameterType(i);
151
            ptypes[i] = translate(origPtype);
152
            changePtypes |= origPtype != ptypes[i];
153
        }
154
        try {
155
            if (changeRtype) {
156
                final Field rtypeFld = MethodType.class.getDeclaredField("rtype");   //NOI18N
157
                rtypeFld.setAccessible(true);
158
                rtypeFld.set(mt, rtype);
159
            }
160
            if (changePtypes) {
161
                final Field ptypesFld = MethodType.class.getDeclaredField("ptypes");   //NOI18N
162
                ptypesFld.setAccessible(true);
163
                ptypesFld.set(mt, ptypes);
164
            }
165
        } catch (ReflectiveOperationException e) {
166
            LOG.warning(e.getMessage());
167
        }
168
        return mt;
169
    }
170
171
    private static Class<?> translate(Class<?> clz) {
172
        if (clz.isPrimitive()) {
173
            return clz;
174
        } else if (clz.isArray()) {
175
            final Class<?> oldCompType = clz.getComponentType();
176
            final Class<?> newCompType = translate(oldCompType);
177
            if (oldCompType != newCompType) {
178
                clz = Array.newInstance(newCompType, 0).getClass();
179
            }
180
            return clz;
181
        } else {
182
            try {
183
                final String fqn = clz.getName();
184
                return LambdaMetafactory.class.getClassLoader().loadClass(fqn);
185
            } catch (ClassNotFoundException cnf) {
186
                return clz;
187
            }
188
        }
189
    }
190
}

Return to bug 253549