Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/HiddenClass/P/Q/HiddenClassSigTest.java
41162 views
/*1* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @requires vm.jvmti26* @library /test/lib27* @modules java.base/jdk.internal.misc28* jdk.compiler29* @compile HiddenClassSigTest.java30* @run main/othervm/native -agentlib:HiddenClassSigTest P.Q.HiddenClassSigTest31*/3233package P.Q;3435import java.io.ByteArrayOutputStream;36import java.io.File;37import java.io.FileInputStream;3839import java.lang.invoke.MethodHandles;40import java.lang.invoke.MethodHandles.Lookup;41import java.nio.file.Files;42import java.nio.file.Path;43import java.nio.file.Paths;4445import jdk.test.lib.Utils;464748interface HCInterf<T> {49String hcMethod(T t);50}5152class HiddenClassSig<T> implements HCInterf<T> {53private String realTest() { return "HiddenClassSig: "; }5455public String hcMethod(T t) {56String str = realTest();57return str + t.toString();58}59}6061public class HiddenClassSigTest {62private static void log(String str) { System.out.println(str); }6364private static final String HCName = "P/Q/HiddenClassSig.class";65private static final Path CLASSES_DIR = Paths.get(Utils.TEST_CLASSES);66private static final String LOG_PREFIX = "HiddenClassSigTest: ";6768static native void checkHiddenClass(Class klass, String sig);69static native void checkHiddenClassArray(Class array, String sig);70static native boolean checkFailed(); // get native agent failing status7172static {73try {74System.loadLibrary("HiddenClassSigTest");75} catch (UnsatisfiedLinkError ule) {76System.err.println("Could not load HiddenClassSigTest library");77System.err.println("java.library.path: "78+ System.getProperty("java.library.path"));79throw ule;80}81}8283static Class<?> defineHiddenClass(String classFileName) throws Exception {84Lookup lookup = MethodHandles.lookup();85byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(classFileName));86Class<?> hc = lookup.defineHiddenClass(bytes, false).lookupClass();87return hc;88}8990// print all name variations91static void logClassInfo(Class<?> klass) {92log("\n### Testing class: " + klass);93log(LOG_PREFIX + "isHidden: " + klass.isHidden());94log(LOG_PREFIX + "getName: " + klass.getName());95log(LOG_PREFIX + "typeName: " + klass.getTypeName());96log(LOG_PREFIX + "toString: " + klass.toString());97log(LOG_PREFIX + "toGenStr: " + klass.toGenericString());98log(LOG_PREFIX + "elem type: " + klass.componentType());99}100101private static final String HC_NAME = "P.Q.HiddenClassSig";102private static final String HC_SUFFIX_REGEX = "0x[0-9a-f]+";103104static boolean checkName(Class<?> klass, String name, String toString) {105boolean failed = false;106String regex = "";107Class<?> c = klass;108109// for an array add the prefix "[" for each dimension110while (c.isArray()) {111regex = "\\[" + regex;112c = c.componentType();113}114// construct the expected name115if (klass.isArray()) {116regex += "L" + HC_NAME + "/" + HC_SUFFIX_REGEX + ";";117} else {118regex = HC_NAME + "/" + HC_SUFFIX_REGEX;119}120// check the name matches the expected121if (!name.matches(regex)) {122log("Test FAIL: result of Class::getName" + " \"" + name + "\" does not match " + regex);123failed = true;124}125// check the string name matches the expected126if (!toString.matches("class " + regex)) {127log("Test FAIL: result of Class::toString" + " \"" + name + "\" does not match " + regex);128failed = true;129}130return failed;131}132133static boolean checkTypeName(Class<?> klass, String name) {134boolean failed = false;135// construct the expected type name136String regex = HC_NAME + "/" + HC_SUFFIX_REGEX;137Class<?> c = klass;138139// for an array add the suffix "[]" for each dimension140while (c.isArray()) {141c = c.componentType();142regex = regex + "\\[\\]";143}144// check the type name matches the expected145if (!name.matches(regex)) {146log("Test FAIL: result of Class::getTypeName" + " \"" + name + "\" does not match " + regex);147failed = true;148}149return failed;150}151152static boolean checkGenericString(Class<?> klass, String name) {153boolean failed = false;154Class<?> c = klass;155// construct the expected generic string156String regex = HC_NAME + "/" + HC_SUFFIX_REGEX + "<T>";157158// add the expected name prefix for a non-array class159if (!klass.isArray()) {160regex = "class " + regex;161}162// for an array get the bottom component class163while (c.isArray()) {164c = c.componentType();165regex = regex + "\\[\\]";166}167// check the generic string matches the expected168if (!name.matches(regex)) {169log("Test FAIL: result of Class::toGenericString" + " \"" + name + "\" does not match " + regex);170failed = true;171}172return failed;173}174175static boolean checkDescriptorString(Class<?> klass, String name) {176boolean failed = false;177// construct the expected descriptor string178String regex = "L" + HC_NAME.replace('.', '/') + "." + HC_SUFFIX_REGEX + ";";179Class<?> c = klass;180181// for array get the bottom component class182while (c.isArray()) {183regex = "\\[" + regex;184c = c.componentType();185}186// check the descriptor string matches the expected187if (!name.matches(regex)) {188log("Test FAIL: result of Class::descriptorString" + " \"" + name + "\" does not match " + regex);189failed = true;190}191return failed;192}193194static boolean testClass(Class<?> klass) {195boolean failed = false;196logClassInfo(klass);197198// verify all name variations199failed |= checkName(klass, klass.getName(), klass.toString());200failed |= checkTypeName(klass, klass.getTypeName());201failed |= checkGenericString(klass, klass.toGenericString());202failed |= checkDescriptorString(klass, klass.descriptorString());203204// an array class is never hidden205if (klass.isArray() && klass.isHidden()) {206log("Test FAIL: an array class is never hidden");207failed = true;208}209210// verify hidden class array or class by the native agent211if (klass.isArray()) {212checkHiddenClassArray(klass, klass.descriptorString());213} else {214checkHiddenClass(klass, klass.descriptorString());215}216return failed;217}218219public static void main(String args[]) throws Exception {220log(LOG_PREFIX + "started");221222// define a hidden class to test223Class<?> hc = defineHiddenClass(HCName);224225// allocate a hidden class instance to test226HCInterf<String> testObj = (HCInterf<String>)hc.newInstance();227228String str = testObj.hcMethod("Test generic hidden class");229log(LOG_PREFIX + "hc.hcMethod() returned string: " + str);230231// test all hidden class name/signature variations232boolean failed = testClass(hc);233234// test all hidden class array name/signature variations235Class<?> hcArr = hc.arrayType();236failed |= testClass(hcArr);237238// test all hidden class double array name/signature variations239Class<?> hcArrArr = hcArr.arrayType();240failed |= testClass(hcArrArr);241242if (failed) { // check the java part failing status243throw new RuntimeException("FAIL: failed status from java part");244}245if (checkFailed()) { // check the native agent failing status246throw new RuntimeException("FAIL: failed status from native agent");247}248log(LOG_PREFIX + "finished");249}250}251252253