• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wuwen5 / hessian / 17882005206

20 Sep 2025 01:06PM UTC coverage: 70.892% (+1.5%) from 69.377%
17882005206

push

github

web-flow
refactor: code clean (#50)

* refactor: code clean

* refactor: code clean,remove hessian1 code

* refactor: fix HessianDebugState

1780 of 2691 branches covered (66.15%)

Branch coverage included in aggregate %.

4226 of 5781 relevant lines covered (73.1%)

3.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.64
hessian2-codec/src/main/java/io/github/wuwen5/hessian/io/UnsafeSerializer.java
1
/*
2
 * Copyright (c) 2001-2008 Caucho Technology, Inc.  All rights reserved.
3
 *
4
 * The Apache Software License, Version 1.1
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 *
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in
15
 *    the documentation and/or other materials provided with the
16
 *    distribution.
17
 *
18
 * 3. The end-user documentation included with the redistribution, if
19
 *    any, must include the following acknowlegement:
20
 *       "This product includes software developed by the
21
 *        Caucho Technology (http://www.caucho.com/)."
22
 *    Alternately, this acknowlegement may appear in the software itself,
23
 *    if and wherever such third-party acknowlegements normally appear.
24
 *
25
 * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
26
 *    endorse or promote products derived from this software without prior
27
 *    written permission. For written permission, please contact
28
 *    info@caucho.com.
29
 *
30
 * 5. Products derived from this software may not be called "Resin"
31
 *    nor may "Resin" appear in their names without prior written
32
 *    permission of Caucho Technology.
33
 *
34
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37
 * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
 *
46
 * @author Scott Ferguson
47
 */
48

49
package io.github.wuwen5.hessian.io;
50

51
import com.caucho.hessian.HessianUnshared;
52
import java.io.IOException;
53
import java.lang.ref.SoftReference;
54
import java.lang.reflect.Field;
55
import java.lang.reflect.Modifier;
56
import java.util.ArrayList;
57
import java.util.Collections;
58
import java.util.WeakHashMap;
59
import lombok.extern.slf4j.Slf4j;
60
import sun.misc.Unsafe;
61

62
/**
63
 * Serializing an object for known object types.
64
 */
65
@Slf4j
3✔
66
public class UnsafeSerializer extends AbstractSerializer {
67
    private static boolean isEnabled;
68
    private static final Unsafe UNSAFE;
69

70
    private static final WeakHashMap<Class<?>, SoftReference<UnsafeSerializer>> SERIALIZER_MAP = new WeakHashMap<>();
4✔
71

72
    private Field[] fields;
73
    private FieldSerializer[] fieldSerializers;
74

75
    public static boolean isEnabled() {
76
        return isEnabled;
2✔
77
    }
78

79
    public UnsafeSerializer(Class<?> cl) {
2✔
80
        introspect(cl);
3✔
81
    }
1✔
82

83
    public static UnsafeSerializer create(Class<?> cl) {
84
        synchronized (SERIALIZER_MAP) {
4✔
85
            SoftReference<UnsafeSerializer> baseRef = SERIALIZER_MAP.get(cl);
5✔
86

87
            UnsafeSerializer base = baseRef != null ? baseRef.get() : null;
8✔
88

89
            if (base == null) {
2✔
90
                if (cl.isAnnotationPresent(HessianUnshared.class)
6✔
91
                        || cl.isAnnotationPresent(io.github.wuwen5.hessian.HessianUnshared.class)) {
2!
92
                    base = new UnsafeUnsharedSerializer(cl);
6✔
93
                } else {
94
                    base = new UnsafeSerializer(cl);
5✔
95
                }
96

97
                baseRef = new SoftReference<>(base);
5✔
98
                SERIALIZER_MAP.put(cl, baseRef);
5✔
99
            }
100

101
            return base;
4✔
102
        }
103
    }
104

105
    protected void introspect(Class<?> cl) {
106
        ArrayList<Field> primitiveFields = new ArrayList<>();
4✔
107
        ArrayList<Field> compoundFields = new ArrayList<>();
4✔
108

109
        for (; cl != null; cl = cl.getSuperclass()) {
6✔
110

111
            for (Field field : cl.getDeclaredFields()) {
17✔
112
                if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
8✔
113
                    continue;
1✔
114
                }
115

116
                if (field.getType().isPrimitive()
5✔
117
                        || (field.getType().getName().startsWith("java.lang.")
6✔
118
                                && !field.getType().equals(Object.class))) {
4✔
119
                    primitiveFields.add(field);
5✔
120
                } else {
121
                    compoundFields.add(field);
4✔
122
                }
123
            }
124
        }
125

126
        ArrayList<Field> fieldArrayList = new ArrayList<>();
4✔
127
        fieldArrayList.addAll(primitiveFields);
4✔
128
        fieldArrayList.addAll(compoundFields);
4✔
129
        Collections.reverse(fieldArrayList);
2✔
130

131
        this.fields = new Field[fieldArrayList.size()];
5✔
132
        fieldArrayList.toArray(this.fields);
5✔
133

134
        fieldSerializers = new FieldSerializer[this.fields.length];
6✔
135

136
        for (int i = 0; i < this.fields.length; i++) {
9✔
137
            fieldSerializers[i] = getFieldSerializer(this.fields[i]);
9✔
138
        }
139
    }
1✔
140

141
    @Override
142
    public void writeObject(Object obj, AbstractHessianEncoder out) throws IOException {
143
        if (out.addRef(obj)) {
4✔
144
            return;
1✔
145
        }
146

147
        Class<?> cl = obj.getClass();
3✔
148

149
        int ref = out.writeObjectBegin(cl.getName());
5✔
150

151
        if (ref >= 0) {
2✔
152
            writeInstance(obj, out);
5✔
153
        } else if (ref == -1) {
3!
154
            writeDefinition20(out);
3✔
155
            out.writeObjectBegin(cl.getName());
5✔
156
            writeInstance(obj, out);
4✔
157
        }
158
    }
1✔
159

160
    @Override
161
    protected void writeObject10(Object obj, AbstractHessianEncoder out) throws IOException {
162
        for (int i = 0; i < fields.length; i++) {
×
163
            Field field = fields[i];
×
164

165
            out.writeString(field.getName());
×
166

167
            fieldSerializers[i].serialize(out, obj);
×
168
        }
169

170
        out.writeMapEnd();
×
171
    }
×
172

173
    private void writeDefinition20(AbstractHessianEncoder out) throws IOException {
174
        out.writeClassFieldLength(fields.length);
5✔
175

176
        for (Field field : fields) {
17✔
177
            out.writeString(field.getName());
4✔
178
        }
179
    }
1✔
180

181
    @Override
182
    public final void writeInstance(Object obj, AbstractHessianEncoder out) throws IOException {
183
        try {
184
            for (FieldSerializer fieldSerializer : this.fieldSerializers) {
17✔
185
                fieldSerializer.serialize(out, obj);
4✔
186
            }
187
        } catch (RuntimeException e) {
×
188
            throw new IllegalStateException(
×
189
                    e.getMessage() + "\n class: " + obj.getClass().getName() + " (object=" + obj + ")", e);
×
190
        } catch (IOException e) {
×
191
            throw new IOExceptionWrapper(
×
192
                    e.getMessage() + "\n class: " + obj.getClass().getName() + " (object=" + obj + ")", e);
×
193
        }
1✔
194
    }
1✔
195

196
    private static FieldSerializer getFieldSerializer(Field field) {
197
        Class<?> type = field.getType();
3✔
198

199
        if (boolean.class.equals(type)) {
4✔
200
            return new BooleanFieldSerializer(field);
5✔
201
        } else if (byte.class.equals(type)) {
4✔
202
            return new ByteFieldSerializer(field);
5✔
203
        } else if (char.class.equals(type)) {
4✔
204
            return new CharFieldSerializer(field);
5✔
205
        } else if (short.class.equals(type)) {
4✔
206
            return new ShortFieldSerializer(field);
5✔
207
        } else if (int.class.equals(type)) {
4✔
208
            return new IntFieldSerializer(field);
5✔
209
        } else if (long.class.equals(type)) {
4✔
210
            return new LongFieldSerializer(field);
5✔
211
        } else if (double.class.equals(type)) {
4✔
212
            return new DoubleFieldSerializer(field);
5✔
213
        } else if (float.class.equals(type)) {
4✔
214
            return new FloatFieldSerializer(field);
5✔
215
        } else if (String.class.equals(type)) {
4✔
216
            return new StringFieldSerializer(field);
5✔
217
        } else if (java.util.Date.class.equals(type)
6✔
218
                || java.sql.Date.class.equals(type)
4✔
219
                || java.sql.Timestamp.class.equals(type)
4✔
220
                || java.sql.Time.class.equals(type)) {
2✔
221
            return new DateFieldSerializer(field);
5✔
222
        } else {
223
            return new ObjectFieldSerializer(field);
5✔
224
        }
225
    }
226

227
    abstract static class FieldSerializer {
3✔
228
        abstract void serialize(AbstractHessianEncoder out, Object obj) throws IOException;
229
    }
230

231
    static final class ObjectFieldSerializer extends FieldSerializer {
232
        private final Field field;
233
        private final long offset;
234

235
        ObjectFieldSerializer(Field field) {
2✔
236
            this.field = field;
3✔
237
            offset = UNSAFE.objectFieldOffset(field);
5✔
238

239
            if (offset == Unsafe.INVALID_FIELD_OFFSET) throw new IllegalStateException();
5!
240
        }
1✔
241

242
        @Override
243
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
244
            try {
245
                Object value = UNSAFE.getObject(obj, offset);
6✔
246

247
                out.writeObject(value);
3✔
248
            } catch (RuntimeException e) {
×
249
                throw new IllegalStateException(
×
250
                        e.getMessage() + "\n field: "
×
251
                                + field.getDeclaringClass().getName()
×
252
                                + '.' + field.getName(),
×
253
                        e);
254
            } catch (IOException e) {
×
255
                throw new IOExceptionWrapper(
×
256
                        e.getMessage() + "\n field: "
×
257
                                + field.getDeclaringClass().getName()
×
258
                                + '.' + field.getName(),
×
259
                        e);
260
            }
1✔
261
        }
1✔
262
    }
263

264
    static final class BooleanFieldSerializer extends FieldSerializer {
265
        private final long offset;
266

267
        BooleanFieldSerializer(Field field) {
2✔
268
            offset = UNSAFE.objectFieldOffset(field);
5✔
269

270
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
271
                throw new IllegalStateException();
×
272
            }
273
        }
1✔
274

275
        @Override
276
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
277
            boolean value = UNSAFE.getBoolean(obj, offset);
6✔
278

279
            out.writeBoolean(value);
3✔
280
        }
1✔
281
    }
282

283
    static final class ByteFieldSerializer extends FieldSerializer {
284
        private final long offset;
285

286
        ByteFieldSerializer(Field field) {
2✔
287
            offset = UNSAFE.objectFieldOffset(field);
5✔
288

289
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
290
                throw new IllegalStateException();
×
291
            }
292
        }
1✔
293

294
        @Override
295
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
296
            int value = UNSAFE.getByte(obj, offset);
6✔
297

298
            out.writeInt(value);
3✔
299
        }
1✔
300
    }
301

302
    static final class CharFieldSerializer extends FieldSerializer {
303
        private final long offset;
304

305
        CharFieldSerializer(Field field) {
2✔
306
            offset = UNSAFE.objectFieldOffset(field);
5✔
307

308
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
309
                throw new IllegalStateException();
×
310
            }
311
        }
1✔
312

313
        @Override
314
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
315
            char value = UNSAFE.getChar(obj, offset);
6✔
316

317
            out.writeString(String.valueOf(value));
4✔
318
        }
1✔
319
    }
320

321
    static final class ShortFieldSerializer extends FieldSerializer {
322
        private final long offset;
323

324
        ShortFieldSerializer(Field field) {
2✔
325
            offset = UNSAFE.objectFieldOffset(field);
5✔
326

327
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
328
                throw new IllegalStateException();
×
329
            }
330
        }
1✔
331

332
        @Override
333
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
334
            int value = UNSAFE.getShort(obj, offset);
6✔
335

336
            out.writeInt(value);
3✔
337
        }
1✔
338
    }
339

340
    static final class IntFieldSerializer extends FieldSerializer {
341
        private final long offset;
342

343
        IntFieldSerializer(Field field) {
2✔
344
            offset = UNSAFE.objectFieldOffset(field);
5✔
345

346
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
347
                throw new IllegalStateException();
×
348
            }
349
        }
1✔
350

351
        @Override
352
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
353
            int value = UNSAFE.getInt(obj, offset);
6✔
354

355
            out.writeInt(value);
3✔
356
        }
1✔
357
    }
358

359
    static final class LongFieldSerializer extends FieldSerializer {
360
        private final long offset;
361

362
        LongFieldSerializer(Field field) {
2✔
363
            offset = UNSAFE.objectFieldOffset(field);
5✔
364

365
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
366
                throw new IllegalStateException();
×
367
            }
368
        }
1✔
369

370
        @Override
371
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
372
            long value = UNSAFE.getLong(obj, offset);
6✔
373

374
            out.writeLong(value);
3✔
375
        }
1✔
376
    }
377

378
    static final class FloatFieldSerializer extends FieldSerializer {
379
        private final long offset;
380

381
        FloatFieldSerializer(Field field) {
2✔
382
            offset = UNSAFE.objectFieldOffset(field);
5✔
383

384
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
385
                throw new IllegalStateException();
×
386
            }
387
        }
1✔
388

389
        @Override
390
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
391
            double value = UNSAFE.getFloat(obj, offset);
7✔
392

393
            out.writeDouble(value);
3✔
394
        }
1✔
395
    }
396

397
    static final class DoubleFieldSerializer extends FieldSerializer {
398
        private final long offset;
399

400
        DoubleFieldSerializer(Field field) {
2✔
401
            offset = UNSAFE.objectFieldOffset(field);
5✔
402

403
            if (offset == Unsafe.INVALID_FIELD_OFFSET) throw new IllegalStateException();
5!
404
        }
1✔
405

406
        @Override
407
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
408
            double value = UNSAFE.getDouble(obj, offset);
6✔
409

410
            out.writeDouble(value);
3✔
411
        }
1✔
412
    }
413

414
    static final class StringFieldSerializer extends FieldSerializer {
415
        private final long offset;
416

417
        StringFieldSerializer(Field field) {
2✔
418
            offset = UNSAFE.objectFieldOffset(field);
5✔
419

420
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
421
                throw new IllegalStateException();
×
422
            }
423
        }
1✔
424

425
        @Override
426
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
427
            String value = (String) UNSAFE.getObject(obj, offset);
7✔
428

429
            out.writeString(value);
3✔
430
        }
1✔
431
    }
432

433
    static final class DateFieldSerializer extends FieldSerializer {
434
        private final long offset;
435

436
        DateFieldSerializer(Field field) {
2✔
437
            offset = UNSAFE.objectFieldOffset(field);
5✔
438

439
            if (offset == Unsafe.INVALID_FIELD_OFFSET) {
5!
440
                throw new IllegalStateException();
×
441
            }
442
        }
1✔
443

444
        @Override
445
        void serialize(AbstractHessianEncoder out, Object obj) throws IOException {
446
            java.util.Date value = (java.util.Date) UNSAFE.getObject(obj, offset);
7✔
447

448
            if (value == null) {
2!
449
                out.writeNull();
×
450
            } else {
451
                out.writeUTCDate(value.getTime());
4✔
452
            }
453
        }
1✔
454
    }
455

456
    static {
457
        boolean isEnabled = false;
2✔
458
        Unsafe unsafe = null;
2✔
459

460
        try {
461
            Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
3✔
462
            Field theUnsafe = null;
2✔
463
            for (Field field : unsafeClass.getDeclaredFields()) {
17✔
464
                if ("theUnsafe".equals(field.getName())) {
5✔
465
                    theUnsafe = field;
2✔
466
                }
467
            }
468

469
            if (theUnsafe != null) {
2!
470
                theUnsafe.setAccessible(true);
3✔
471
                unsafe = (Unsafe) theUnsafe.get(null);
5✔
472
            }
473

474
            isEnabled = unsafe != null;
5!
475

476
            String unsafeProp = System.getProperty("com.caucho.hessian.unsafe");
3✔
477

478
            if ("false".equals(unsafeProp)) {
4!
479
                isEnabled = false;
×
480
            }
481
        } catch (Throwable e) {
×
482
            log.error(e.toString(), e);
×
483
        }
1✔
484

485
        UNSAFE = unsafe;
2✔
486
        UnsafeSerializer.isEnabled = isEnabled;
2✔
487
    }
1✔
488
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc