author | sherman |
Wed, 21 Oct 2009 11:40:40 -0700 | |
changeset 4161 | 679d00486dc6 |
parent 3861 | a98a057ec335 |
child 5506 | 202f599c92aa |
permissions | -rw-r--r-- |
2 | 1 |
/* |
2 |
* Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. |
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
package java.util.logging; |
|
27 |
import java.util.*; |
|
2632
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
28 |
import java.util.concurrent.atomic.AtomicInteger; |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
29 |
import java.util.concurrent.atomic.AtomicLong; |
2 | 30 |
import java.io.*; |
31 |
||
2947
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
32 |
import sun.misc.JavaLangAccess; |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
33 |
import sun.misc.SharedSecrets; |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
34 |
|
2 | 35 |
/** |
36 |
* LogRecord objects are used to pass logging requests between |
|
37 |
* the logging framework and individual log Handlers. |
|
38 |
* <p> |
|
39 |
* When a LogRecord is passed into the logging framework it |
|
40 |
* logically belongs to the framework and should no longer be |
|
41 |
* used or updated by the client application. |
|
42 |
* <p> |
|
43 |
* Note that if the client application has not specified an |
|
44 |
* explicit source method name and source class name, then the |
|
45 |
* LogRecord class will infer them automatically when they are |
|
46 |
* first accessed (due to a call on getSourceMethodName or |
|
47 |
* getSourceClassName) by analyzing the call stack. Therefore, |
|
48 |
* if a logging Handler wants to pass off a LogRecord to another |
|
49 |
* thread, or to transmit it over RMI, and if it wishes to subsequently |
|
50 |
* obtain method name or class name information it should call |
|
51 |
* one of getSourceClassName or getSourceMethodName to force |
|
52 |
* the values to be filled in. |
|
53 |
* <p> |
|
54 |
* <b> Serialization notes:</b> |
|
55 |
* <ul> |
|
56 |
* <li>The LogRecord class is serializable. |
|
57 |
* |
|
58 |
* <li> Because objects in the parameters array may not be serializable, |
|
59 |
* during serialization all objects in the parameters array are |
|
60 |
* written as the corresponding Strings (using Object.toString). |
|
61 |
* |
|
62 |
* <li> The ResourceBundle is not transmitted as part of the serialized |
|
63 |
* form, but the resource bundle name is, and the recipient object's |
|
64 |
* readObject method will attempt to locate a suitable resource bundle. |
|
65 |
* |
|
66 |
* </ul> |
|
67 |
* |
|
68 |
* @since 1.4 |
|
69 |
*/ |
|
70 |
||
71 |
public class LogRecord implements java.io.Serializable { |
|
2632
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
72 |
private static final AtomicLong globalSequenceNumber |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
73 |
= new AtomicLong(0); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
74 |
|
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
75 |
/** |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
76 |
* The default value of threadID will be the current thread's |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
77 |
* thread id, for ease of correlation, unless it is greater than |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
78 |
* MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
79 |
* our promise to keep threadIDs unique by avoiding collisions due |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
80 |
* to 32-bit wraparound. Unfortunately, LogRecord.getThreadID() |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
81 |
* returns int, while Thread.getId() returns long. |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
82 |
*/ |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
83 |
private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2; |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
84 |
|
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
85 |
private static final AtomicInteger nextThreadId |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
86 |
= new AtomicInteger(MIN_SEQUENTIAL_THREAD_ID); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
87 |
|
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
88 |
private static final ThreadLocal<Integer> threadIds |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
89 |
= new ThreadLocal<Integer>(); |
2 | 90 |
|
91 |
/** |
|
92 |
* @serial Logging message level |
|
93 |
*/ |
|
94 |
private Level level; |
|
95 |
||
96 |
/** |
|
97 |
* @serial Sequence number |
|
98 |
*/ |
|
99 |
private long sequenceNumber; |
|
100 |
||
101 |
/** |
|
102 |
* @serial Class that issued logging call |
|
103 |
*/ |
|
104 |
private String sourceClassName; |
|
105 |
||
106 |
/** |
|
107 |
* @serial Method that issued logging call |
|
108 |
*/ |
|
109 |
private String sourceMethodName; |
|
110 |
||
111 |
/** |
|
112 |
* @serial Non-localized raw message text |
|
113 |
*/ |
|
114 |
private String message; |
|
115 |
||
116 |
/** |
|
117 |
* @serial Thread ID for thread that issued logging call. |
|
118 |
*/ |
|
119 |
private int threadID; |
|
120 |
||
121 |
/** |
|
122 |
* @serial Event time in milliseconds since 1970 |
|
123 |
*/ |
|
124 |
private long millis; |
|
125 |
||
126 |
/** |
|
127 |
* @serial The Throwable (if any) associated with log message |
|
128 |
*/ |
|
129 |
private Throwable thrown; |
|
130 |
||
131 |
/** |
|
132 |
* @serial Name of the source Logger. |
|
133 |
*/ |
|
134 |
private String loggerName; |
|
135 |
||
136 |
/** |
|
137 |
* @serial Resource bundle name to localized log message. |
|
138 |
*/ |
|
139 |
private String resourceBundleName; |
|
140 |
||
141 |
private transient boolean needToInferCaller; |
|
142 |
private transient Object parameters[]; |
|
143 |
private transient ResourceBundle resourceBundle; |
|
144 |
||
145 |
/** |
|
2632
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
146 |
* Returns the default value for a new LogRecord's threadID. |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
147 |
*/ |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
148 |
private int defaultThreadID() { |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
149 |
long tid = Thread.currentThread().getId(); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
150 |
if (tid < MIN_SEQUENTIAL_THREAD_ID) { |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
151 |
return (int) tid; |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
152 |
} else { |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
153 |
Integer id = threadIds.get(); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
154 |
if (id == null) { |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
155 |
id = nextThreadId.getAndIncrement(); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
156 |
threadIds.set(id); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
157 |
} |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
158 |
return id; |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
159 |
} |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
160 |
} |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
161 |
|
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
162 |
/** |
2 | 163 |
* Construct a LogRecord with the given level and message values. |
164 |
* <p> |
|
165 |
* The sequence property will be initialized with a new unique value. |
|
166 |
* These sequence values are allocated in increasing order within a VM. |
|
167 |
* <p> |
|
168 |
* The millis property will be initialized to the current time. |
|
169 |
* <p> |
|
170 |
* The thread ID property will be initialized with a unique ID for |
|
171 |
* the current thread. |
|
172 |
* <p> |
|
173 |
* All other properties will be initialized to "null". |
|
174 |
* |
|
175 |
* @param level a logging level value |
|
176 |
* @param msg the raw non-localized logging message (may be null) |
|
177 |
*/ |
|
178 |
public LogRecord(Level level, String msg) { |
|
179 |
// Make sure level isn't null, by calling random method. |
|
180 |
level.getClass(); |
|
181 |
this.level = level; |
|
182 |
message = msg; |
|
183 |
// Assign a thread ID and a unique sequence number. |
|
2632
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
184 |
sequenceNumber = globalSequenceNumber.getAndIncrement(); |
9779b9cbae42
6278014: java.util.logging.LogRecord.getThreadID() should provide real thread id
martin
parents:
2
diff
changeset
|
185 |
threadID = defaultThreadID(); |
2 | 186 |
millis = System.currentTimeMillis(); |
187 |
needToInferCaller = true; |
|
188 |
} |
|
189 |
||
190 |
/** |
|
3853 | 191 |
* Get the source Logger's name. |
2 | 192 |
* |
193 |
* @return source logger name (may be null) |
|
194 |
*/ |
|
195 |
public String getLoggerName() { |
|
196 |
return loggerName; |
|
197 |
} |
|
198 |
||
199 |
/** |
|
3853 | 200 |
* Set the source Logger's name. |
2 | 201 |
* |
202 |
* @param name the source logger name (may be null) |
|
203 |
*/ |
|
204 |
public void setLoggerName(String name) { |
|
205 |
loggerName = name; |
|
206 |
} |
|
207 |
||
208 |
/** |
|
209 |
* Get the localization resource bundle |
|
210 |
* <p> |
|
211 |
* This is the ResourceBundle that should be used to localize |
|
212 |
* the message string before formatting it. The result may |
|
213 |
* be null if the message is not localizable, or if no suitable |
|
214 |
* ResourceBundle is available. |
|
215 |
*/ |
|
216 |
public ResourceBundle getResourceBundle() { |
|
217 |
return resourceBundle; |
|
218 |
} |
|
219 |
||
220 |
/** |
|
221 |
* Set the localization resource bundle. |
|
222 |
* |
|
223 |
* @param bundle localization bundle (may be null) |
|
224 |
*/ |
|
225 |
public void setResourceBundle(ResourceBundle bundle) { |
|
226 |
resourceBundle = bundle; |
|
227 |
} |
|
228 |
||
229 |
/** |
|
230 |
* Get the localization resource bundle name |
|
231 |
* <p> |
|
232 |
* This is the name for the ResourceBundle that should be |
|
233 |
* used to localize the message string before formatting it. |
|
234 |
* The result may be null if the message is not localizable. |
|
235 |
*/ |
|
236 |
public String getResourceBundleName() { |
|
237 |
return resourceBundleName; |
|
238 |
} |
|
239 |
||
240 |
/** |
|
241 |
* Set the localization resource bundle name. |
|
242 |
* |
|
243 |
* @param name localization bundle name (may be null) |
|
244 |
*/ |
|
245 |
public void setResourceBundleName(String name) { |
|
246 |
resourceBundleName = name; |
|
247 |
} |
|
248 |
||
249 |
/** |
|
250 |
* Get the logging message level, for example Level.SEVERE. |
|
251 |
* @return the logging message level |
|
252 |
*/ |
|
253 |
public Level getLevel() { |
|
254 |
return level; |
|
255 |
} |
|
256 |
||
257 |
/** |
|
258 |
* Set the logging message level, for example Level.SEVERE. |
|
259 |
* @param level the logging message level |
|
260 |
*/ |
|
261 |
public void setLevel(Level level) { |
|
262 |
if (level == null) { |
|
263 |
throw new NullPointerException(); |
|
264 |
} |
|
265 |
this.level = level; |
|
266 |
} |
|
267 |
||
268 |
/** |
|
269 |
* Get the sequence number. |
|
270 |
* <p> |
|
271 |
* Sequence numbers are normally assigned in the LogRecord |
|
272 |
* constructor, which assigns unique sequence numbers to |
|
273 |
* each new LogRecord in increasing order. |
|
274 |
* @return the sequence number |
|
275 |
*/ |
|
276 |
public long getSequenceNumber() { |
|
277 |
return sequenceNumber; |
|
278 |
} |
|
279 |
||
280 |
/** |
|
281 |
* Set the sequence number. |
|
282 |
* <p> |
|
283 |
* Sequence numbers are normally assigned in the LogRecord constructor, |
|
284 |
* so it should not normally be necessary to use this method. |
|
285 |
*/ |
|
286 |
public void setSequenceNumber(long seq) { |
|
287 |
sequenceNumber = seq; |
|
288 |
} |
|
289 |
||
290 |
/** |
|
291 |
* Get the name of the class that (allegedly) issued the logging request. |
|
292 |
* <p> |
|
293 |
* Note that this sourceClassName is not verified and may be spoofed. |
|
294 |
* This information may either have been provided as part of the |
|
295 |
* logging call, or it may have been inferred automatically by the |
|
296 |
* logging framework. In the latter case, the information may only |
|
297 |
* be approximate and may in fact describe an earlier call on the |
|
298 |
* stack frame. |
|
299 |
* <p> |
|
300 |
* May be null if no information could be obtained. |
|
301 |
* |
|
302 |
* @return the source class name |
|
303 |
*/ |
|
304 |
public String getSourceClassName() { |
|
305 |
if (needToInferCaller) { |
|
306 |
inferCaller(); |
|
307 |
} |
|
308 |
return sourceClassName; |
|
309 |
} |
|
310 |
||
311 |
/** |
|
312 |
* Set the name of the class that (allegedly) issued the logging request. |
|
313 |
* |
|
314 |
* @param sourceClassName the source class name (may be null) |
|
315 |
*/ |
|
316 |
public void setSourceClassName(String sourceClassName) { |
|
317 |
this.sourceClassName = sourceClassName; |
|
318 |
needToInferCaller = false; |
|
319 |
} |
|
320 |
||
321 |
/** |
|
322 |
* Get the name of the method that (allegedly) issued the logging request. |
|
323 |
* <p> |
|
324 |
* Note that this sourceMethodName is not verified and may be spoofed. |
|
325 |
* This information may either have been provided as part of the |
|
326 |
* logging call, or it may have been inferred automatically by the |
|
327 |
* logging framework. In the latter case, the information may only |
|
328 |
* be approximate and may in fact describe an earlier call on the |
|
329 |
* stack frame. |
|
330 |
* <p> |
|
331 |
* May be null if no information could be obtained. |
|
332 |
* |
|
333 |
* @return the source method name |
|
334 |
*/ |
|
335 |
public String getSourceMethodName() { |
|
336 |
if (needToInferCaller) { |
|
337 |
inferCaller(); |
|
338 |
} |
|
339 |
return sourceMethodName; |
|
340 |
} |
|
341 |
||
342 |
/** |
|
343 |
* Set the name of the method that (allegedly) issued the logging request. |
|
344 |
* |
|
345 |
* @param sourceMethodName the source method name (may be null) |
|
346 |
*/ |
|
347 |
public void setSourceMethodName(String sourceMethodName) { |
|
348 |
this.sourceMethodName = sourceMethodName; |
|
349 |
needToInferCaller = false; |
|
350 |
} |
|
351 |
||
352 |
/** |
|
353 |
* Get the "raw" log message, before localization or formatting. |
|
354 |
* <p> |
|
355 |
* May be null, which is equivalent to the empty string "". |
|
356 |
* <p> |
|
357 |
* This message may be either the final text or a localization key. |
|
358 |
* <p> |
|
359 |
* During formatting, if the source logger has a localization |
|
360 |
* ResourceBundle and if that ResourceBundle has an entry for |
|
361 |
* this message string, then the message string is replaced |
|
362 |
* with the localized value. |
|
363 |
* |
|
364 |
* @return the raw message string |
|
365 |
*/ |
|
366 |
public String getMessage() { |
|
367 |
return message; |
|
368 |
} |
|
369 |
||
370 |
/** |
|
371 |
* Set the "raw" log message, before localization or formatting. |
|
372 |
* |
|
373 |
* @param message the raw message string (may be null) |
|
374 |
*/ |
|
375 |
public void setMessage(String message) { |
|
376 |
this.message = message; |
|
377 |
} |
|
378 |
||
379 |
/** |
|
380 |
* Get the parameters to the log message. |
|
381 |
* |
|
382 |
* @return the log message parameters. May be null if |
|
383 |
* there are no parameters. |
|
384 |
*/ |
|
385 |
public Object[] getParameters() { |
|
386 |
return parameters; |
|
387 |
} |
|
388 |
||
389 |
/** |
|
390 |
* Set the parameters to the log message. |
|
391 |
* |
|
392 |
* @param parameters the log message parameters. (may be null) |
|
393 |
*/ |
|
394 |
public void setParameters(Object parameters[]) { |
|
395 |
this.parameters = parameters; |
|
396 |
} |
|
397 |
||
398 |
/** |
|
399 |
* Get an identifier for the thread where the message originated. |
|
400 |
* <p> |
|
401 |
* This is a thread identifier within the Java VM and may or |
|
402 |
* may not map to any operating system ID. |
|
403 |
* |
|
404 |
* @return thread ID |
|
405 |
*/ |
|
406 |
public int getThreadID() { |
|
407 |
return threadID; |
|
408 |
} |
|
409 |
||
410 |
/** |
|
411 |
* Set an identifier for the thread where the message originated. |
|
412 |
* @param threadID the thread ID |
|
413 |
*/ |
|
414 |
public void setThreadID(int threadID) { |
|
415 |
this.threadID = threadID; |
|
416 |
} |
|
417 |
||
418 |
/** |
|
419 |
* Get event time in milliseconds since 1970. |
|
420 |
* |
|
421 |
* @return event time in millis since 1970 |
|
422 |
*/ |
|
423 |
public long getMillis() { |
|
424 |
return millis; |
|
425 |
} |
|
426 |
||
427 |
/** |
|
428 |
* Set event time. |
|
429 |
* |
|
430 |
* @param millis event time in millis since 1970 |
|
431 |
*/ |
|
432 |
public void setMillis(long millis) { |
|
433 |
this.millis = millis; |
|
434 |
} |
|
435 |
||
436 |
/** |
|
437 |
* Get any throwable associated with the log record. |
|
438 |
* <p> |
|
439 |
* If the event involved an exception, this will be the |
|
440 |
* exception object. Otherwise null. |
|
441 |
* |
|
442 |
* @return a throwable |
|
443 |
*/ |
|
444 |
public Throwable getThrown() { |
|
445 |
return thrown; |
|
446 |
} |
|
447 |
||
448 |
/** |
|
449 |
* Set a throwable associated with the log event. |
|
450 |
* |
|
451 |
* @param thrown a throwable (may be null) |
|
452 |
*/ |
|
453 |
public void setThrown(Throwable thrown) { |
|
454 |
this.thrown = thrown; |
|
455 |
} |
|
456 |
||
457 |
private static final long serialVersionUID = 5372048053134512534L; |
|
458 |
||
459 |
/** |
|
460 |
* @serialData Default fields, followed by a two byte version number |
|
461 |
* (major byte, followed by minor byte), followed by information on |
|
462 |
* the log record parameter array. If there is no parameter array, |
|
463 |
* then -1 is written. If there is a parameter array (possible of zero |
|
464 |
* length) then the array length is written as an integer, followed |
|
465 |
* by String values for each parameter. If a parameter is null, then |
|
466 |
* a null String is written. Otherwise the output of Object.toString() |
|
467 |
* is written. |
|
468 |
*/ |
|
469 |
private void writeObject(ObjectOutputStream out) throws IOException { |
|
470 |
// We have to call defaultWriteObject first. |
|
471 |
out.defaultWriteObject(); |
|
472 |
||
473 |
// Write our version number. |
|
474 |
out.writeByte(1); |
|
475 |
out.writeByte(0); |
|
476 |
if (parameters == null) { |
|
477 |
out.writeInt(-1); |
|
478 |
return; |
|
479 |
} |
|
480 |
out.writeInt(parameters.length); |
|
481 |
// Write string values for the parameters. |
|
482 |
for (int i = 0; i < parameters.length; i++) { |
|
483 |
if (parameters[i] == null) { |
|
484 |
out.writeObject(null); |
|
485 |
} else { |
|
486 |
out.writeObject(parameters[i].toString()); |
|
487 |
} |
|
488 |
} |
|
489 |
} |
|
490 |
||
491 |
private void readObject(ObjectInputStream in) |
|
492 |
throws IOException, ClassNotFoundException { |
|
493 |
// We have to call defaultReadObject first. |
|
494 |
in.defaultReadObject(); |
|
495 |
||
496 |
// Read version number. |
|
497 |
byte major = in.readByte(); |
|
498 |
byte minor = in.readByte(); |
|
499 |
if (major != 1) { |
|
500 |
throw new IOException("LogRecord: bad version: " + major + "." + minor); |
|
501 |
} |
|
502 |
int len = in.readInt(); |
|
503 |
if (len == -1) { |
|
504 |
parameters = null; |
|
505 |
} else { |
|
506 |
parameters = new Object[len]; |
|
507 |
for (int i = 0; i < parameters.length; i++) { |
|
508 |
parameters[i] = in.readObject(); |
|
509 |
} |
|
510 |
} |
|
511 |
// If necessary, try to regenerate the resource bundle. |
|
512 |
if (resourceBundleName != null) { |
|
513 |
try { |
|
514 |
resourceBundle = ResourceBundle.getBundle(resourceBundleName); |
|
515 |
} catch (MissingResourceException ex) { |
|
516 |
// This is not a good place to throw an exception, |
|
517 |
// so we simply leave the resourceBundle null. |
|
518 |
resourceBundle = null; |
|
519 |
} |
|
520 |
} |
|
521 |
||
522 |
needToInferCaller = false; |
|
523 |
} |
|
524 |
||
525 |
// Private method to infer the caller's class and method names |
|
526 |
private void inferCaller() { |
|
527 |
needToInferCaller = false; |
|
2947
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
528 |
JavaLangAccess access = SharedSecrets.getJavaLangAccess(); |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
529 |
Throwable throwable = new Throwable(); |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
530 |
int depth = access.getStackTraceDepth(throwable); |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
531 |
|
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
532 |
String logClassName = "java.util.logging.Logger"; |
3861
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
533 |
String plogClassName = "sun.util.logging.PlatformLogger"; |
2947
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
534 |
boolean lookingForLogger = true; |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
535 |
for (int ix = 0; ix < depth; ix++) { |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
536 |
// Calling getStackTraceElement directly prevents the VM |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
537 |
// from paying the cost of building the entire stack frame. |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
538 |
StackTraceElement frame = |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
539 |
access.getStackTraceElement(throwable, ix); |
2 | 540 |
String cname = frame.getClassName(); |
2947
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
541 |
if (lookingForLogger) { |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
542 |
// Skip all frames until we have found the first logger frame. |
3861
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
543 |
if (cname.equals(logClassName) || cname.startsWith(plogClassName)) { |
2947
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
544 |
lookingForLogger = false; |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
545 |
} |
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
546 |
} else { |
3861
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
547 |
if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) { |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
548 |
// skip reflection call |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
549 |
if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) { |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
550 |
// We've found the relevant frame. |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
551 |
setSourceClassName(cname); |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
552 |
setSourceMethodName(frame.getMethodName()); |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
553 |
return; |
a98a057ec335
6882376: Add internal support for JRE implementation to eliminate the dependency on logging
mchung
parents:
3853
diff
changeset
|
554 |
} |
2947
b0135c99348e
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
martin
parents:
2632
diff
changeset
|
555 |
} |
2 | 556 |
} |
557 |
} |
|
558 |
// We haven't found a suitable frame, so just punt. This is |
|
559 |
// OK as we are only committed to making a "best effort" here. |
|
560 |
} |
|
561 |
} |