AndroidBufferAllocator.java 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (c) 2009-2019 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.util;
  33. import java.lang.reflect.Field;
  34. import java.nio.Buffer;
  35. import java.nio.ByteBuffer;
  36. import java.util.HashMap;
  37. import java.util.Map;
  38. /**
  39. * @author Jesus Oliver
  40. */
  41. public class AndroidBufferAllocator implements BufferAllocator {
  42. // We make use of the ReflectionAllocator to remove the inner buffer
  43. private static final ReflectionAllocator reflectionAllocator = new ReflectionAllocator();
  44. private static final String[] wrapperClassNames = {
  45. "java.nio.ByteBufferAsFloatBuffer",
  46. "java.nio.ByteBufferAsIntBuffer",
  47. "java.nio.ByteBufferAsDoubleBuffer",
  48. "java.nio.ByteBufferAsShortBuffer",
  49. "java.nio.ByteBufferAsLongBuffer",
  50. "java.nio.ByteBufferAsCharBuffer",
  51. };
  52. private static final String[] possibleBufferFieldNames = {"bb", "byteBuffer"};
  53. // Keep track of ByteBuffer field by the wrapper class
  54. private static final Map<Class, Field> fieldIndex = new HashMap<>();
  55. static {
  56. for (String className : wrapperClassNames) {
  57. try {
  58. Class clazz = Class.forName(className);
  59. // loop for all possible field names in android
  60. for (String fieldName : possibleBufferFieldNames) {
  61. try {
  62. Field field = clazz.getDeclaredField(fieldName);
  63. field.setAccessible(true);
  64. fieldIndex.put(clazz, field);
  65. break;
  66. } catch (NoSuchFieldException e) {
  67. }
  68. }
  69. } catch (ClassNotFoundException ex) {
  70. }
  71. }
  72. }
  73. @Override
  74. /**
  75. * This function search the inner direct buffer of the android specific wrapped buffer classes
  76. * and destroys it using the reflection allocator method.
  77. *
  78. * @param toBeDestroyed The direct buffer that will be "cleaned".
  79. *
  80. */
  81. public void destroyDirectBuffer(Buffer toBeDestroyed) {
  82. // If it is a wrapped buffer, get it's inner direct buffer field and destroy it
  83. Field field = fieldIndex.get(toBeDestroyed.getClass());
  84. if (field != null) {
  85. try {
  86. ByteBuffer innerBuffer = (ByteBuffer) field.get(toBeDestroyed);
  87. if (innerBuffer != null) {
  88. // Destroy it using the reflection method
  89. reflectionAllocator.destroyDirectBuffer(innerBuffer);
  90. }
  91. } catch (IllegalAccessException ex) {
  92. }
  93. } else {
  94. // It is not a wrapped buffer, use default reflection allocator to remove it instead.
  95. reflectionAllocator.destroyDirectBuffer(toBeDestroyed);
  96. }
  97. }
  98. @Override
  99. public ByteBuffer allocate(int size) {
  100. return ByteBuffer.allocateDirect(size);
  101. }
  102. }