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( 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( 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( 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( 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( 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 * 2 ),
337 new Long( available * 2 ) );
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( 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 * 4 ),
381 new Long( available * 4 ) );
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( int requested ) throws OutOfMemoryError
409 {
410 if ( requested < 0 )
411 {
412 throw new IllegalArgumentException( Integer.toString( requested ) );
413 }
414
415 double[] ret = null;
416 int retries = this.getMaximumRetries();
417
418 do
419 {
420 final long available = this.getAvailableDoubles();
421
422 if ( available < requested )
423 {
424 this.logOutOfMemoryWarning( new Long( requested * 8 ),
425 new Long( available * 8 ) );
426
427 this.forceGarbageCollection(
428 this.getMaximumRetries() - retries );
429
430 }
431 else
432 {
433 ret = new double[ requested ];
434 }
435
436 }
437 while ( ret == null && retries-- > 0 );
438
439 if ( ret == null )
440 {
441 throw new OutOfMemoryError();
442 }
443
444 return ret;
445 }
446
447 public long getAvailableBooleans()
448 {
449 return this.getAvailableBytes();
450 }
451
452 public boolean[] allocateBoolean( int requested ) throws OutOfMemoryError
453 {
454 if ( requested < 0 )
455 {
456 throw new IllegalArgumentException( Integer.toString( requested ) );
457 }
458
459 boolean[] ret = null;
460 int retries = this.getMaximumRetries();
461
462 do
463 {
464 final long available = this.getAvailableBooleans();
465
466 if ( available < requested )
467 {
468 this.logOutOfMemoryWarning( new Long( requested ),
469 new Long( available ) );
470
471 this.forceGarbageCollection(
472 this.getMaximumRetries() - retries );
473
474 }
475 else
476 {
477 ret = new boolean[ requested ];
478 }
479
480 }
481 while ( ret == null && retries-- > 0 );
482
483 if ( ret == null )
484 {
485 throw new OutOfMemoryError();
486 }
487
488 return ret;
489 }
490
491
492
493
494
495 private Integer maximumPercent;
496
497
498 private Integer maximumRetries;
499
500
501
502
503
504
505
506
507
508
509
510 public DefaultMemoryManager( final int maximumPercent,
511 final int maximumRetries )
512 {
513 if ( maximumPercent >= 0 && maximumPercent <= 100 )
514 {
515 this.maximumPercent = new Integer( maximumPercent );
516 }
517 if ( maximumRetries > 0 )
518 {
519 this.maximumRetries = new Integer( maximumRetries );
520 }
521 }
522
523
524
525
526
527
528 private int getMaximumRetries()
529 {
530 if ( this.maximumRetries == null )
531 {
532 this.maximumRetries = this.getDefaultMaximumRetries();
533 }
534
535 return this.maximumRetries.intValue();
536 }
537
538
539
540
541
542
543 private int getMaximumPercent()
544 {
545 if ( this.maximumPercent == null )
546 {
547 this.maximumPercent = this.getDefaultMaximumPercent();
548 }
549
550 return this.maximumPercent.intValue();
551 }
552
553
554
555
556
557
558
559
560 private void logOutOfMemoryWarning( final Long requestedByte,
561 final Long availableByte )
562 {
563 this.getLogger().warn( this.getOutOfMemoryWarningMessage(
564 this.getLocale(), availableByte, requestedByte ) );
565
566 }
567
568
569
570
571
572
573
574
575 private void forceGarbageCollection( final int repetition )
576 {
577 this.getLogger().warn( this.getForcingGarbageCollectionMessage(
578 this.getLocale(), new Integer( repetition ) ) );
579
580 System.gc();
581 }
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600 private String getOutOfMemoryWarningMessage( final Locale locale,
601 final java.lang.Number neededMemory,
602 final java.lang.Number availableMemory )
603 {
604 return ContainerFactory.getContainer().
605 getMessage( this, "outOfMemoryWarning", locale,
606 new Object[]
607 {
608 neededMemory,
609 availableMemory
610 });
611
612 }
613
614
615
616
617
618
619
620
621
622
623
624 private String getForcingGarbageCollectionMessage( final Locale locale,
625 final java.lang.Number retry )
626 {
627 return ContainerFactory.getContainer().
628 getMessage( this, "forcingGarbageCollection", locale,
629 new Object[]
630 {
631 retry
632 });
633
634 }
635
636
637
638
639 }