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

Return to bug 253549