1 /** 2 * Copyright 2006-2017 the original author or authors. 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 org.objenesis.strategy; 17 18 import org.objenesis.ObjenesisException; 19 20 import java.lang.reflect.Field; 21 22 /** 23 * List of constants describing the currently used platform. 24 * 25 * @author Henri Tremblay 26 */ 27 public final class PlatformDescription { 28 29 /** JVM_NAME prefix for JRockit */ 30 public static final String JROCKIT = "BEA"; 31 32 /** JVM_NAME prefix for GCJ */ 33 public static final String GNU = "GNU libgcj"; 34 35 /** JVM_NAME prefix for Java HotSpot */ 36 public static final String HOTSPOT = "Java HotSpot"; 37 38 /** 39 * JVM_NAME prefix for Java HotSpot 40 * 41 * @deprecated Use {@link #HOTSPOT} instead 42 */ 43 @Deprecated 44 public static final String SUN = HOTSPOT; 45 46 /** JVM_NAME prefix for the OpenJDK */ 47 public static final String OPENJDK = "OpenJDK"; 48 49 /** JVM_NAME prefix for Aonix PERC */ 50 public static final String PERC = "PERC"; 51 52 /** JVM_NAME prefix for Dalvik/Android */ 53 public static final String DALVIK = "Dalvik"; 54 55 /** Java specification version */ 56 public static final String SPECIFICATION_VERSION = System 57 .getProperty("java.specification.version"); 58 59 /** JVM version */ 60 public static final String VM_VERSION = System.getProperty("java.runtime.version"); 61 62 /** JVM version */ 63 public static final String VM_INFO = System.getProperty("java.vm.info"); 64 65 /** VM vendor version */ 66 public static final String VENDOR_VERSION = System.getProperty("java.vm.version"); 67 68 /** VM vendor name */ 69 public static final String VENDOR = System.getProperty("java.vm.vendor"); 70 71 /** JVM name */ 72 public static final String JVM_NAME = System.getProperty("java.vm.name"); 73 74 /** Android version. Will be 0 for none android platform */ 75 public static final int ANDROID_VERSION = getAndroidVersion(); 76 77 /** Flag telling if this version of Android is based on the OpenJDK */ 78 public static final boolean IS_ANDROID_OPENJDK = getIsAndroidOpenJDK(); 79 80 /** Google App Engine version or null is we are not on GAE */ 81 public static final String GAE_VERSION = getGaeRuntimeVersion(); 82 83 /** 84 * Describes the platform. Outputs Java version and vendor. 85 * 86 * @return Description of the current platform 87 */ describePlatform()88 public static String describePlatform() { 89 String desc = "Java " + SPECIFICATION_VERSION + " (" 90 + "VM vendor name=\"" + VENDOR + "\", " 91 + "VM vendor version=" + VENDOR_VERSION + ", " 92 + "JVM name=\"" + JVM_NAME + "\", " 93 + "JVM version=" + VM_VERSION + ", " 94 + "JVM info=" + VM_INFO; 95 96 // Add the API level is it's an Android platform 97 int androidVersion = ANDROID_VERSION; 98 if(androidVersion != 0) { 99 desc += ", API level=" + ANDROID_VERSION; 100 } 101 desc += ")"; 102 103 return desc; 104 } 105 106 /** 107 * Check if the current JVM is of the type passed in parameter. Normally, this will be a constant 108 * from this class. We basically do 109 * <code>System.getProperty("java.vm.name").startWith(name)</code>. 110 * 111 * @param name jvm name we are looking for 112 * @return if it's the requested JVM 113 */ isThisJVM(String name)114 public static boolean isThisJVM(String name) { 115 return JVM_NAME.startsWith(name); 116 } 117 118 /** 119 * Check if this JVM is an Android JVM based on OpenJDK. 120 * 121 * @return if it's an Android version based on the OpenJDK. Will return false if this JVM isn't an Android JVM at all 122 */ isAndroidOpenJDK()123 public static boolean isAndroidOpenJDK() { 124 return IS_ANDROID_OPENJDK; 125 } 126 getIsAndroidOpenJDK()127 private static boolean getIsAndroidOpenJDK() { 128 if(getAndroidVersion() == 0) { 129 return false; // Not android at all 130 } 131 // Sadly, Android N is still API 23. So we can't base ourselves on the API level to know if it is an OpenJDK 132 // version or not 133 String bootClasspath = System.getProperty("java.boot.class.path"); 134 return bootClasspath != null && bootClasspath.toLowerCase().contains("core-oj.jar"); 135 } 136 isGoogleAppEngine()137 public static boolean isGoogleAppEngine() { 138 return GAE_VERSION != null; 139 } 140 getGaeRuntimeVersion()141 private static String getGaeRuntimeVersion() { 142 return System.getProperty("com.google.appengine.runtime.version"); 143 } 144 getAndroidVersion()145 private static int getAndroidVersion() { 146 if(!isThisJVM(DALVIK)) { 147 return 0; 148 } 149 return getAndroidVersion0(); 150 } 151 getAndroidVersion0()152 private static int getAndroidVersion0() { 153 Class<?> clazz; 154 try { 155 clazz = Class.forName("android.os.Build$VERSION"); 156 } 157 catch(ClassNotFoundException e) { 158 throw new ObjenesisException(e); 159 } 160 Field field; 161 try { 162 field = clazz.getField("SDK_INT"); 163 } 164 catch(NoSuchFieldException e) { 165 // Might be a really old API (before 4), go for SDK 166 return getOldAndroidVersion(clazz); 167 } 168 int version; 169 try { 170 version = (Integer) field.get(null); 171 } 172 catch(IllegalAccessException e) { 173 throw new RuntimeException(e); 174 } 175 return version; 176 } 177 getOldAndroidVersion(Class<?> versionClass)178 private static int getOldAndroidVersion(Class<?> versionClass) { 179 Field field; 180 try { 181 field = versionClass.getField("SDK"); 182 } 183 catch(NoSuchFieldException e) { 184 throw new ObjenesisException(e); 185 } 186 String version; 187 try { 188 version = (String) field.get(null); 189 } 190 catch(IllegalAccessException e) { 191 throw new RuntimeException(e); 192 } 193 return Integer.parseInt(version); 194 } 195 PlatformDescription()196 private PlatformDescription() { 197 } 198 } 199