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

raphw / byte-buddy / #850

27 Feb 2026 03:40PM UTC coverage: 83.044% (+0.02%) from 83.021%
#850

push

raphw
[release] Release new version

29635 of 35686 relevant lines covered (83.04%)

0.83 hits per line

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

85.71
/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/Nexus.java
1
/*
2
 * Copyright 2014 - Present Rafael Winterhalter
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
 */
16
package net.bytebuddy.dynamic;
17

18
import net.bytebuddy.utility.nullability.AlwaysNull;
19
import net.bytebuddy.utility.nullability.MaybeNull;
20

21
import java.lang.ref.Reference;
22
import java.lang.ref.ReferenceQueue;
23
import java.lang.ref.WeakReference;
24
import java.util.concurrent.ConcurrentHashMap;
25
import java.util.concurrent.ConcurrentMap;
26

27
/**
28
 * <p>
29
 * This nexus is a global dispatcher for initializing classes with
30
 * {@link net.bytebuddy.implementation.LoadedTypeInitializer}s. To do so, this class is to be loaded
31
 * by the system class loader in an explicit manner. Any instrumented class is then injected a code
32
 * block into its static type initializer that makes a call to this very same nexus which had the
33
 * loaded type initializer registered before hand.
34
 * </p>
35
 * <p>
36
 * <b>Note</b>: Availability of the {@link Nexus} class and its injection into the system class loader
37
 * can be disabled entirely by setting the {@link Nexus#PROPERTY} system property to {@code false}.
38
 * </p>
39
 * <p>
40
 * <b>Important</b>: The nexus must never be accessed directly but only by the {@link NexusAccessor}
41
 * which makes sure that the nexus is loaded by the system class loader. Otherwise, a class might not
42
 * be able to initialize itself if it is loaded by different class loader that does not have the
43
 * system class loader in its hierarchy.
44
 * </p>
45
 */
46
public class Nexus extends WeakReference<ClassLoader> {
47

48
    /**
49
     * A system property that allows to disable the use of the {@link Nexus} class which is normally injected into the system class loader.
50
     */
51
    public static final String PROPERTY = "net.bytebuddy.nexus.disabled";
52

53
    /**
54
     * An type-safe constant for a non-operational reference queue.
55
     */
56
    @AlwaysNull
57
    private static final ReferenceQueue<ClassLoader> NO_QUEUE = null;
1✔
58

59
    /**
60
     * A map of keys identifying a loaded type by its name and class loader mapping their
61
     * potential {@link net.bytebuddy.implementation.LoadedTypeInitializer} where the class
62
     * loader of these initializers is however irrelevant.
63
     */
64
    private static final ConcurrentMap<Nexus, Object> TYPE_INITIALIZERS = new ConcurrentHashMap<Nexus, Object>();
1✔
65

66
    /**
67
     * The name of a type for which a loaded type initializer is registered.
68
     */
69
    private final String name;
70

71
    /**
72
     * The class loader's hash code upon registration.
73
     */
74
    private final int classLoaderHashCode;
75

76
    /**
77
     * A random value that uniquely identifies a Nexus entry in order to avoid conflicts when
78
     * applying the self-initialization strategy in multiple transformations.
79
     */
80
    private final int identification;
81

82
    /**
83
     * Creates a key for identifying a loaded type initializer.
84
     *
85
     * @param type           The loaded type for which a key is to be created.
86
     * @param identification An identification for the initializer to run.
87
     */
88
    private Nexus(Class<?> type, int identification) {
89
        this(nonAnonymous(type.getName()), type.getClassLoader(), NO_QUEUE, identification);
1✔
90
    }
1✔
91

92
    /**
93
     * Creates a key for identifying a loaded type initializer.
94
     *
95
     * @param name           The name of a type for which a loaded type initializer is registered.
96
     * @param classLoader    The class loader for which a loaded type initializer is registered.
97
     * @param referenceQueue The reference queue to notify upon the class loader's collection or {@code null} if no queue should be notified.
98
     * @param identification An identification for the initializer to run.
99
     */
100
    private Nexus(String name, @MaybeNull ClassLoader classLoader, @MaybeNull ReferenceQueue<? super ClassLoader> referenceQueue, int identification) {
101
        super(classLoader, classLoader == null
1✔
102
                ? null
103
                : referenceQueue);
104
        this.name = name;
1✔
105
        classLoaderHashCode = System.identityHashCode(classLoader);
1✔
106
        this.identification = identification;
1✔
107
    }
1✔
108

109
    /**
110
     * Normalizes a type name if it is loaded by an anonymous class loader.
111
     *
112
     * @param typeName The name as returned by {@link Class#getName()}.
113
     * @return The non-anonymous name of the given class.
114
     */
115
    private static String nonAnonymous(String typeName) {
116
        int anonymousLoaderIndex = typeName.indexOf('/');
1✔
117
        return anonymousLoaderIndex == -1
1✔
118
                ? typeName
119
                : typeName.substring(0, anonymousLoaderIndex);
×
120
    }
121

122
    /**
123
     * <p>
124
     * Initializes a loaded type. This method must only be invoked via the system class loader.
125
     * </p>
126
     * <p>
127
     * <b>Important</b>: This method must never be called directly but only by using a {@link NexusAccessor.InitializationAppender} which enforces to
128
     * access this class for the system class loader to assure a VM global singleton. This avoids a duplication of the class if this nexus is loaded
129
     * by different class loaders. For this reason, the last parameter must not use a Byte Buddy specific type as those types can be loaded by
130
     * different class loaders, too. Any access of the instance is done using Java reflection instead.
131
     * </p>
132
     *
133
     * @param type           The loaded type to initialize.
134
     * @param identification An identification for the initializer to run.
135
     * @throws Exception If an exception occurs.
136
     */
137
    @SuppressWarnings("unused")
138
    public static void initialize(Class<?> type, int identification) throws Exception {
139
        Object typeInitializer = TYPE_INITIALIZERS.remove(new Nexus(type, identification));
1✔
140
        if (typeInitializer != null) {
1✔
141
            Class.forName("net.bytebuddy.implementation.LoadedTypeInitializer",
1✔
142
                    true,
143
                    typeInitializer.getClass().getClassLoader()).getMethod("onLoad", Class.class).invoke(typeInitializer, type);
1✔
144
        }
145
    }
1✔
146

147
    /**
148
     * <p>
149
     * Registers a new loaded type initializer.
150
     * </p>
151
     * <p>
152
     * <b>Important</b>: This method must never be called directly but only by using a {@link NexusAccessor} which enforces to access this class
153
     * for the system class loader to assure a VM global singleton. This avoids a duplication of the class if this nexus is loaded by different class
154
     * loaders. For this reason, the last parameter must not use a Byte Buddy specific type as those types can be loaded by different class loaders,
155
     * too. Any access of the instance is done using Java reflection instead.
156
     * </p>
157
     *
158
     * @param name            The name of the type for the loaded type initializer.
159
     * @param classLoader     The class loader of the type for the loaded type initializer.
160
     * @param referenceQueue  The reference queue to notify upon the class loader's collection which will be enqueued a reference which can be
161
     *                        handed to {@link Nexus#clean(Reference)} or {@code null} if no reference queue should be notified.
162
     * @param identification  An identification for the initializer to run.
163
     * @param typeInitializer The type initializer to register. The initializer must be an instance
164
     *                        of {@link net.bytebuddy.implementation.LoadedTypeInitializer} where
165
     *                        it does however not matter which class loader loaded this latter type.
166
     */
167
    public static void register(String name, @MaybeNull ClassLoader classLoader, @MaybeNull ReferenceQueue<? super ClassLoader> referenceQueue, int identification, Object typeInitializer) {
168
        TYPE_INITIALIZERS.put(new Nexus(name, classLoader, referenceQueue, identification), typeInitializer);
1✔
169
    }
1✔
170

171
    /**
172
     * <p>
173
     * Cleans any stale entries from this nexus. Entries are considered stale if their class loader was collected before a class was initialized.
174
     * </p>
175
     * <p>
176
     * <b>Important</b>: This method must never be called directly but only by using a {@link NexusAccessor} which enforces to access this class
177
     * for the system class loader to assure a VM global singleton. This avoids a duplication of the class if this nexus is loaded by different class
178
     * loaders. For this reason, the last parameter must not use a Byte Buddy specific type as those types can be loaded by different class loaders,
179
     * too. Any access of the instance is done using Java reflection instead.
180
     * </p>
181
     *
182
     * @param reference The stale reference to clean.
183
     */
184
    public static void clean(Reference<? super ClassLoader> reference) {
185
        TYPE_INITIALIZERS.remove(reference);
1✔
186
    }
1✔
187

188
    @Override
189
    public int hashCode() {
190
        int result = name.hashCode();
1✔
191
        result = 31 * result + classLoaderHashCode;
1✔
192
        result = 31 * result + identification;
1✔
193
        return result;
1✔
194
    }
195

196
    @Override
197
    public boolean equals(@MaybeNull Object other) {
198
        if (this == other) {
1✔
199
            return true;
×
200
        } else if (other == null || getClass() != other.getClass()) {
1✔
201
            return false;
×
202
        }
203
        Nexus nexus = (Nexus) other;
1✔
204
        return classLoaderHashCode == nexus.classLoaderHashCode
1✔
205
                && identification == nexus.identification
206
                && name.equals(nexus.name)
1✔
207
                && get() == nexus.get();
1✔
208
    }
209

210
    @Override
211
    public String toString() {
212
        return "Nexus{" +
×
213
                "name='" + name + '\'' +
214
                ", classLoaderHashCode=" + classLoaderHashCode +
215
                ", identification=" + identification +
216
                ", classLoader=" + get() +
×
217
                '}';
218
    }
219
}
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