1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jdtaus.core.lang.ri;
22
23 import java.util.Locale;
24 import org.jdtaus.core.container.ContainerFactory;
25 import org.jdtaus.core.lang.spi.MemoryManager;
26 import org.jdtaus.core.logging.spi.Logger;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class DefaultMemoryManager implements MemoryManager
48 {
49
50
51
52
53
54
55 public DefaultMemoryManager()
56 {
57 super();
58 }
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 private Logger getLogger()
74 {
75 return (Logger) ContainerFactory.getContainer().
76 getDependency( this, "Logger" );
77
78 }
79
80
81
82
83
84
85 private Locale getLocale()
86 {
87 return (Locale) ContainerFactory.getContainer().
88 getDependency( this, "Locale" );
89
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 private java.lang.Integer getDefaultMaximumRetries()
106 {
107 return (java.lang.Integer) ContainerFactory.getContainer().
108 getProperty( this, "defaultMaximumRetries" );
109
110 }
111
112
113
114
115
116
117 private java.lang.Integer getDefaultMaximumPercent()
118 {
119 return (java.lang.Integer) ContainerFactory.getContainer().
120 getProperty( this, "defaultMaximumPercent" );
121
122 }
123
124
125
126
127
128
129 public long getAllocatedPercent()
130 {
131 final Runtime rt = Runtime.getRuntime();
132 final long max = rt.maxMemory();
133 final long limit = ( max / 100L ) * this.getMaximumPercent();
134 return rt.totalMemory() * ( 100L / limit );
135 }
136
137 public long getAvailableBytes()
138 {
139 final Runtime rt = Runtime.getRuntime();
140 final long all = rt.maxMemory() - rt.totalMemory() + rt.freeMemory();
141 return ( all / 100L ) * this.getMaximumPercent();
142 }
143
144 public byte[] allocateBytes( final int requested ) throws OutOfMemoryError
145 {
146 if ( requested < 0 )
147 {
148 throw new IllegalArgumentException( Integer.toString( requested ) );
149 }
150
151 byte[] ret = null;
152 int retries = this.getMaximumRetries();
153
154 do
155 {
156 final long available = this.getAvailableBytes();
157
158 if ( available < requested )
159 {
160 this.logOutOfMemoryWarning( new Long( requested ),
161 new Long( available ) );
162
163 this.forceGarbageCollection(
164 this.getMaximumRetries() - retries );
165
166 }
167 else
168 {
169 ret = new byte[ requested ];
170 }
171
172 }
173 while ( ret == null && retries-- > 0 );
174
175 if ( ret == null )
176 {
177 throw new OutOfMemoryError();
178 }
179
180 return ret;
181 }
182
183 public long getAvailableShorts()
184 {
185 return this.getAvailableBytes() / 2;
186 }
187
188 public short[] allocateShorts( final int requested ) throws OutOfMemoryError
189 {
190 if ( requested < 0 )
191 {
192 throw new IllegalArgumentException( Integer.toString( requested ) );
193 }
194
195 short[] ret = null;
196 int retries = this.getMaximumRetries();
197
198 do
199 {
200 final long available = this.getAvailableShorts();
201
202 if ( available < requested )
203 {
204 this.logOutOfMemoryWarning( new Long( requested * 2 ),
205 new Long( available * 2 ) );
206
207 this.forceGarbageCollection(
208 this.getMaximumRetries() - retries );
209
210 }
211 else
212 {
213 ret = new short[ requested ];
214 }
215
216 }
217 while ( ret == null && retries-- > 0 );
218
219 if ( ret == null )
220 {
221 throw new OutOfMemoryError();
222 }
223
224 return ret;
225 }
226
227 public long getAvailableIntegers()
228 {
229 return this.getAvailableBytes() / 4;
230 }
231
232 public int[] allocateIntegers( final int requested ) throws OutOfMemoryError
233 {
234 if ( requested < 0 )
235 {
236 throw new IllegalArgumentException( Integer.toString( requested ) );
237 }
238
239 int[] ret = null;
240 int retries = this.getMaximumRetries();
241
242 do
243 {
244 final long available = this.getAvailableIntegers();
245 if ( available < requested )
246 {
247 this.logOutOfMemoryWarning( new Long( requested * 4 ),
248 new Long( available * 4 ) );
249
250 this.forceGarbageCollection(
251 this.getMaximumRetries() - retries );
252
253 }
254 else
255 {
256 ret = new int[ requested ];
257 }
258
259
260 }
261 while ( ret == null && retries-- > 0 );
262
263 if ( ret == null )
264 {
265 throw new OutOfMemoryError();
266 }
267
268 return ret;
269 }
270
271 public long getAvailableLongs()
272 {
273 return this.getAvailableBytes() / 8;
274 }
275
276 public long[] allocateLongs( final int requested ) throws OutOfMemoryError
277 {
278 if ( requested < 0 )
279 {
280 throw new IllegalArgumentException( Integer.toString( requested ) );
281 }
282
283 long[] ret = null;
284 int retries = this.getMaximumRetries();
285
286 do
287 {
288 final long available = this.getAvailableLongs();
289
290 if ( available < requested )
291 {
292 this.logOutOfMemoryWarning( new Long( requested * 8 ),
293 new Long( available * 8 ) );
294
295 this.forceGarbageCollection(
296 this.getMaximumRetries() - retries );
297
298 }
299 else
300 {
301 ret = new long[ requested ];
302 }
303
304 }
305 while ( ret == null && retries-- > 0 );
306
307 if ( ret == null )
308 {
309 throw new OutOfMemoryError();
310 }
311
312 return ret;
313 }
314
315 public long getAvailableChars()
316 {
317 return this.getAvailableBytes() / 2;
318 }
319
320 public char[] allocateChars( final int requested ) throws OutOfMemoryError
321 {
322 if ( requested < 0 )
323 {
324 throw new IllegalArgumentException( Integer.toString( requested ) );
325 }
326
327 char[] ret = null;
328 int retries = this.getMaximumRetries();
329
330 do
331 {
332 final long available = this.getAvailableChars();
333
334 if ( available < requested )
335 {
336 this.logOutOfMemoryWarning( new Long( requested * 2L ),
337 new Long( available * 2L ) );
338
339 this.forceGarbageCollection(
340 this.getMaximumRetries() - retries );
341
342 }
343 else
344 {
345 ret = new char[ requested ];
346 }
347
348 }
349 while ( ret == null && retries-- > 0 );
350
351 if ( ret == null )
352 {
353 throw new OutOfMemoryError();
354 }
355
356 return ret;
357 }
358
359 public long getAvailableFloats()
360 {
361 return this.getAvailableBytes() / 4;
362 }
363
364 public float[] allocateFloats( final int requested ) throws OutOfMemoryError
365 {
366 if ( requested < 0 )
367 {
368 throw new IllegalArgumentException( Integer.toString( requested ) );
369 }
370
371 float[] ret = null;
372 int retries = this.getMaximumRetries();
373
374 do
375 {
376 final long available = this.getAvailableFloats();
377
378 if ( available < requested )
379 {
380 this.logOutOfMemoryWarning( new Long( requested * 4L ),
381 new Long( available * 4L ) );
382
383 this.forceGarbageCollection(
384 this.getMaximumRetries() - retries );
385
386 }
387 else
388 {
389 ret = new float[ requested ];
390 }
391
392 }
393 while ( ret == null && retries-- > 0 );
394
395 if ( ret == null )
396 {
397 throw new OutOfMemoryError();
398 }
399
400 return ret;
401 }
402
403 public long getAvailableDoubles()
404 {
405 return this.getAvailableBytes() / 8;
406 }
407
408 public double[] allocateDoubles( final int requested )
409 throws OutOfMemoryError
410 {
411 if ( requested < 0 )
412 {
413 throw new IllegalArgumentException( Integer.toString( requested ) );
414 }
415
416 double[] ret = null;
417 int retries = this.getMaximumRetries();
418
419 do
420 {
421 final long available = this.getAvailableDoubles();
422
423 if ( available < requested )
424 {
425 this.logOutOfMemoryWarning( new Long( requested * 8L ),
426 new Long( available * 8L ) );
427
428 this.forceGarbageCollection(
429 this.getMaximumRetries() - retries );
430
431 }
432 else
433 {
434 ret = new double[ requested ];
435 }
436
437 }
438 while ( ret == null && retries-- > 0 );
439
440 if ( ret == null )
441 {
442 throw new OutOfMemoryError();
443 }
444
445 return ret;
446 }
447
448 public long getAvailableBooleans()
449 {
450 return this.getAvailableBytes();
451 }
452
453 public boolean[] allocateBoolean( final int requested )
454 throws OutOfMemoryError
455 {
456 if ( requested < 0 )
457 {
458 throw new IllegalArgumentException( Integer.toString( requested ) );
459 }
460
461 boolean[] ret = null;
462 int retries = this.getMaximumRetries();
463
464 do
465 {
466 final long available = this.getAvailableBooleans();
467
468 if ( available < requested )
469 {
470 this.logOutOfMemoryWarning( new Long( requested ),
471 new Long( available ) );
472
473 this.forceGarbageCollection(
474 this.getMaximumRetries() - retries );
475
476 }
477 else
478 {
479 ret = new boolean[ requested ];
480 }
481
482 }
483 while ( ret == null && retries-- > 0 );
484
485 if ( ret == null )
486 {
487 throw new OutOfMemoryError();
488 }
489
490 return ret;
491 }
492
493
494
495
496
497 private Integer maximumPercent;
498
499
500 private Integer maximumRetries;
501
502
503
504
505
506
507
508
509
510
511
512 public DefaultMemoryManager( final int maximumPercent,
513 final int maximumRetries )
514 {
515 if ( maximumPercent >= 0 && maximumPercent <= 100 )
516 {
517 this.maximumPercent = new Integer( maximumPercent );
518 }
519 if ( maximumRetries > 0 )
520 {
521 this.maximumRetries = new Integer( maximumRetries );
522 }
523 }
524
525
526
527
528
529
530 private int getMaximumRetries()
531 {
532 if ( this.maximumRetries == null )
533 {
534 this.maximumRetries = this.getDefaultMaximumRetries();
535 }
536
537 return this.maximumRetries.intValue();
538 }
539
540
541
542
543
544
545 private int getMaximumPercent()
546 {
547 if ( this.maximumPercent == null )
548 {
549 this.maximumPercent = this.getDefaultMaximumPercent();
550 }
551
552 return this.maximumPercent.intValue();
553 }
554
555
556
557
558
559
560
561
562 private void logOutOfMemoryWarning( final Long requestedByte,
563 final Long availableByte )
564 {
565 this.getLogger().warn( this.getOutOfMemoryWarningMessage(
566 this.getLocale(), availableByte, requestedByte ) );
567
568 }
569
570
571
572
573
574
575
576
577 private void forceGarbageCollection( final int repetition )
578 {
579 this.getLogger().warn( this.getForcingGarbageCollectionMessage(
580 this.getLocale(), new Integer( repetition ) ) );
581
582 System.gc();
583 }
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602 private String getOutOfMemoryWarningMessage( final Locale locale,
603 final java.lang.Number neededMemory,
604 final java.lang.Number availableMemory )
605 {
606 return ContainerFactory.getContainer().
607 getMessage( this, "outOfMemoryWarning", locale,
608 new Object[]
609 {
610 neededMemory,
611 availableMemory
612 });
613
614 }
615
616
617
618
619
620
621
622
623
624
625
626 private String getForcingGarbageCollectionMessage( final Locale locale,
627 final java.lang.Number retry )
628 {
629 return ContainerFactory.getContainer().
630 getMessage( this, "forcingGarbageCollection", locale,
631 new Object[]
632 {
633 retry
634 });
635
636 }
637
638
639
640
641 }