Isn’t redefining (when you start with a fresh byte code copy) different from retransforming where you are depending on the VM to provide you with the byte code through the class_file_load_hook? I think what we have here is the latter and that no class_file_load_hooks are executed for shared classes? I need to dig deep into what capabilities the j.l.instrument native agent is actually asking for.
/Staffan On 4 dec 2013, at 19:57, Daniel D. Daugherty <daniel.daughe...@oracle.com> wrote: > > Could you please help us with this? Is it a legal scenario to redefine > > shared classes? > > Sorry for the delay in responding. I was on vacation. > > Yes, redefining a shared class is supported via either JVM/TI or > via java.lang.instrument. There should be existing tests that > verify this behavior, but you may have discovered a corner case > by accident. > > Dan > > > On 11/27/13 8:13 AM, Leonid Mesnik wrote: >> I think test should test instrumentation of custom, JDK, JDK shared classes >> as a part of scenario. >> This is how tools could use this mechanism. May be I am wrong. >> >> Also I found >> JDK-5002268 Allow class sharing use with RedefineClasses >> which allow to redefine of classes when class sharing is used. I don't >> exactly know should it work >> for j.l.instrument as well as for JVMTI >> Dan >> Could you please help us with this? Is it a legal scenario to redefine >> shared classes? >> >> Leonid >> >> On 11/27/2013 03:46 PM, Mattias Tobiasson wrote: >>> According to the test documentation and bug references the test verifies >>> the manifest attribute "Can-Redefine-Classes". >>> The test does not mention shared class archive or -Xshare. >>> But maybe the test has found a problem accidentally... >>> >>> Mattias >>> >>> ----- Original Message ----- >>> From: david.hol...@oracle.com >>> To: mattias.tobias...@oracle.com >>> Cc: serviceability-dev@openjdk.java.net >>> Sent: Wednesday, November 27, 2013 12:21:50 PM GMT +01:00 Amsterdam / >>> Berlin / Bern / Rome / Stockholm / Vienna >>> Subject: Re: RFR (S): 6461635: [TESTBUG] BasicTests.sh test fails >>> intermittently >>> >>> On 27/11/2013 8:46 PM, Mattias Tobiasson wrote: >>>> Hi, I now have a reproducer for this test that fails every time. >>>> I just need to verify that it really is a test bug and not a product bug. >>>> >>>> This is a summary of the test: >>>> 1. It loads a javaagent jar that implements ClassFileTransformer. >>>> 2. The agent loads class java.math.BigInteger and expects a callback to >>>> ClassFileTransformer.transform(). But it sometimes does not get that >>>> callback. >>>> >>>> I believe the reason for the intermittent failures are that the jvm flag >>>> -Xshare have different default values on different servers. >>> -Xshare:auto will default to off for server compiler, but on for client >>> >>>> When the reproducer is run with flag "-Xshare:off" it passes every time. >>>> When run with "-Xshare:auto" it fails every time. >>>> When the reproducer is changed to use a dummy class (RedefineDummy) >>>> instead of BigInteger, then the test passes every time no matter what >>>> value -Xshare has. >>>> >>>> My proposed fix for the bug is to use a dummy class instead of BigInteger. >>>> I just need to verify that it is ok that ClassFileTransformer.transform() >>>> is NOT called for BigInteger when -Xshare is enabled. >>> If the whole point of the test is to transform a file from the shared >>> archive then changing to a class not in the archive will defeat that. So >>> you need to verify what the intent of the test is. >>> >>> David >>> >>>> The reproducer is shown below. It loads the javaagent into its own vm so I >>>> don't need to set up multiple jvms. >>>> >>>> public class TestRedefine implements ClassFileTransformer { >>>> >>>> public static void agentmain(String agentArgs, Instrumentation inst) >>>> throws Throwable { >>>> try { >>>> inst.addTransformer(new TestRedefine()); >>>> >>>> ClassLoader.getSystemClassLoader().loadClass("java.math.BigInteger"); >>>> if (!isTransformCalled) { >>>> throw new Exception("transform() NOT called for " + >>>> targetName); >>>> } >>>> } catch (Throwable t) { >>>> t.printStackTrace(); >>>> throw t; >>>> } >>>> } >>>> >>>> public byte[] transform(ClassLoader loader, >>>> String className, >>>> Class<?> classBeingRedefined, >>>> ProtectionDomain protectionDomain, >>>> byte[] classfileBuffer) { >>>> System.out.println("transform called: " + className); >>>> if (className.equals("java/math/BigInteger")) { >>>> isTransformCalled = true; >>>> } >>>> return null; >>>> } >>>> >>>> public static void main(String args[]) throws Exception { >>>> String pid = getProcessId(); >>>> try { >>>> VirtualMachine vm = VirtualMachine.attach(pid); >>>> vm.loadAgent("TestRedefine.jar"); >>>> } catch (Exception e) { >>>> e.printStackTrace(); >>>> throw e; >>>> } >>>> } >>>> >>>> ... more code ... >>>> } >>>> >>>> >>>> >>>> >>>> >>>> ----- Original Message ----- >>>> From: leonid.mes...@oracle.com >>>> To: mattias.tobias...@oracle.com >>>> Cc: serviceability-dev@openjdk.java.net >>>> Sent: Wednesday, November 27, 2013 9:19:37 AM GMT +01:00 Amsterdam / >>>> Berlin / Bern / Rome / Stockholm / Vienna >>>> Subject: Re: RFR (S): 6461635: [TESTBUG] BasicTests.sh test fails >>>> intermittently >>>> >>>> Hi >>>> >>>> Generally I am ok with your comments and fix. However you still needed >>>> to get official review. >>>> >>>> The only question is about failure related from retransformation of >>>> j.l.BigInteger with CDS. >>>> Could it be JDK issue? In this case it would be better to file it as a >>>> part of fix. >>>> I understand that using of CDS and instrumentation of JDK classes is not >>>> related with this test >>>> and your fix make it cleaner. However could you please verify that we >>>> don't have JDK issue here. >>>> >>>> see other comments inline >>>> >>>> On 11/26/2013 08:35 PM, Mattias Tobiasson wrote: >>>>> Hi, >>>>> Thanks for the review. I have summarized the questions and answers: >>>>> >>>>> Q: What is the reason of this intermittent failure? >>>>> A: The test expects the callback ClassFileTransformer.transform() to be >>>>> called when it loads a new class. That function does not seem to be >>>>> called when class sharing is enabled and a previous test has called >>>>> "-Xshare:dump". I am not really sure how ClassFileTransformer works >>>>> together with class sharing. >>>>> I got the idea for -Xshare:dump from this bug: >>>>> https://bugs.openjdk.java.net/browse/JDK-6571866 >>>>> I have verified on jprt that it fails without that flag. I have not been >>>>> able to reproduce a failure when -Xshare:off is set. >>>>> >>>>> Having thought more about the problem, I would like to use another fix. >>>>> The test currently uses java.lang.BigInteger for the transform test. I >>>>> want to change that and instead use my own class (RedefineDummy.java). >>>>> Since loading my own class is not affected by -Xshare, I do not need to >>>>> set the flag. >>>>> Q: You used "output" in finally which is not initialized properly in the >>>>> case of Exception. Could we get another uncaught exception in finally? >>>>> A: output is only sent to getProcessLog() to get a log message. That >>>>> function can handle null values, which it just logs as "null". >>>> Thank you for explanation. >>>>> Q: In getCommandLine(), should we also trim cmd to remove last " "? >>>>> A: Yes. I will fix that. I will also add a check if ProcessBuilder is >>>>> null. >>>> Ok >>>>> Q: waitForJvmPid(String key) throws Throwable. Why throw throwable? >>>>> A: I think there are so many things that can go wrong when starting a >>>>> separate java process, that I do not want to check for expected errors. I >>>>> also don't know how a test writer should handle different kind of >>>>> exceptions from this function. Any exception is logged in the sub >>>>> function. >>>>> Q: Should tryFindJvmPid(String key) be private? Are we going to use it in >>>>> tests or only waitForJvmPid? >>>>> A: Yes, that function may also be used by tests. It is currently not used >>>>> by any test, but it might be useful. >>>> Ok >>>>> Q: Timeouts in function waitForJvmPid(String key)? >>>>> A: I definitely agree of the problem. The reason for not adding a timeout >>>>> parameter to the function is that I do not want the tests to be >>>>> responsible for setting hard coded timeouts. Timeouts should be handled >>>>> by the framework. I know there are plans of adding better process >>>>> handling to jtreg (with ProcessHandler). After that jtreg should be >>>>> better at handling timeouts. >>>>> I will add a flush() to stdout to make sure we log before we wait. >>>> Hope we will update jtreg before get into this issue :) >>>> >>>> Leonid >>>>> Mattias >>>>> >>>>> ----- Original Message ----- >>>>> From: leonid.mes...@oracle.com >>>>> To: mattias.tobias...@oracle.com, serviceability-dev@openjdk.java.net >>>>> Sent: Monday, November 25, 2013 6:26:27 PM GMT +01:00 Amsterdam / Berlin >>>>> / Bern / Rome / Stockholm / Vienna >>>>> Subject: Re: RFR (S): 6461635: [TESTBUG] BasicTests.sh test fails >>>>> intermittently >>>>> >>>>> Hi >>>>> >>>>> I have a couple of high-level questions. >>>>> >>>>> On 11/25/2013 08:28 PM, Mattias Tobiasson wrote: >>>>>> Hi, >>>>>> The test has been updated after the first review. >>>>>> The two java files for each test has been merged to a single file. >>>>>> >>>>>> >>>>>> Updated summary of changes: >>>>>> 1. The real test bug fix is to add flag "-Xshare:off" when starting the >>>>>> "Application" instance. Without that flag, the test for >>>>>> ClassFileTransformer in RedefineAgent.java fails intermittently. The >>>>>> flag is added in function startApplication() in RunnerUtil.java. >>>>> What is the reason of this intermittent failure? >>>>>> 2. Removed all bash scripts. >>>>> Great! >>>>>> 3. Merged the setup bash script and the java test code for each test to >>>>>> a single java file. The old java test code is unchanged, it has just >>>>>> been moved to static nested class in the new java setup file. >>>>>> >>>>>> 4. Added some utility functions to jdk/testlibrary. >>>>> Here some comments about library code. >>>>> http://cr.openjdk.java.net/~miauno/6461635/webrev.01/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java.udiff.html >>>>> >>>>> + try { >>>>> + output = new OutputAnalyzer(this.process); >>>>> + } catch (Throwable t) { >>>>> + String name = Thread.currentThread().getName(); >>>>> + System.out.println(String.format("ProcessThread[%s] >>>>> failed: %s", name, t.toString())); >>>>> + throw t; >>>>> + } finally { >>>>> + String logMsg = >>>>> ProcessTools.getProcessLog(processBuilder, output); >>>>> + System.out.println(logMsg); >>>>> + } >>>>> >>>>> >>>>> You used output in finally which is not initialized properly in the case >>>>> of Exception. >>>>> Could we get another uncaught exception in finally? >>>>> >>>>> http://cr.openjdk.java.net/~miauno/6461635/webrev.01/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java.udiff.html >>>>> >>>>> 1) Same in as previous in executeProcess method. >>>>> >>>>> 2) getCommandLine (...) >>>>> >>>>> + /** >>>>> + * @return The full command line for the ProcessBuilder. >>>>> + */ >>>>> + public static String getCommandLine(ProcessBuilder pb) { >>>>> + StringBuilder cmd = new StringBuilder(); >>>>> + for (String s : pb.command()) { >>>>> + cmd.append(s).append(" "); >>>>> + } >>>>> + return cmd.toString(); >>>>> + } >>>>> >>>>> >>>>> Should we also trim cmd to remove last " "? >>>>> >>>>> http://cr.openjdk.java.net/~miauno/6461635/webrev.01/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java.udiff.html >>>>> >>>>> public static int waitForJvmPid(String key) throws Throwable { >>>>> >>>>> >>>>> Why it throw Trowable? Could we deal with exceptions in this method and >>>>> re-throw some more meaningful exception here? >>>>> Could you force flush for out here: >>>>> >>>>> System.out.println("waitForJvmPid: Waiting for key '" + key + "'"); >>>>> >>>>> Hope it should be enough. It is scary to investigate such "timeouts". >>>>> Would it be better to add some >>>>> internal timeout in testlibrary? Really jtreg doesn't kill all processes >>>>> and we have alive java processes in such case. >>>>> For samevm tests timeouts are even worse. There is no good way to kill >>>>> test in samevm. >>>>> >>>>> Should be >>>>> >>>>> public static int tryFindJvmPid(String key) throws Throwable { >>>>> >>>>> private? Are we going to use it in tests or only waitForJvmPid? >>>>> >>>>> Leonid >>>>>> 5. Moved exit code check from the common utility function in >>>>>> ProcessThread.java to the test JstatdTest.java. The check is moved to >>>>>> the test because other tests in the future may have other expected exit >>>>>> codes. >>>>>> >>>>>> >>>>>> Webrev: >>>>>> http://cr.openjdk.java.net/~miauno/6461635/webrev.01/ >>>>>> >>>>>> Bug: >>>>>> https://bugs.openjdk.java.net/browse/JDK-6461635 >>>>>> >>>>>> Mattias >>>>>> >>>>>> >>>>>> ----- Original Message ----- >>>>>> From: mattias.tobias...@oracle.com >>>>>> To: mikael.a...@oracle.com >>>>>> Cc: serviceability-dev@openjdk.java.net, alan.bate...@oracle.com >>>>>> Sent: Thursday, November 21, 2013 9:22:11 AM GMT +01:00 Amsterdam / >>>>>> Berlin / Bern / Rome / Stockholm / Vienna >>>>>> Subject: Re: RFR (S): 6461635: [TESTBUG] BasicTests.sh test fails >>>>>> intermittently >>>>>> >>>>>> I agree that merging both files in a single file may be good. >>>>>> The main reason why I did not do that is that I wanted to keep the >>>>>> history of the existing test. If I copy the test to a new file, all >>>>>> history of the code is lost. >>>>>> >>>>>> But this test bug was reported 8 years ago, and I don't believe much has >>>>>> changed in the code since then. So keeping the history may not be that >>>>>> important. >>>>>> >>>>>> Mattias >>>>>> >>>>>> ----- Original Message ----- >>>>>> From: mikael.a...@oracle.com >>>>>> To: mattias.tobias...@oracle.com, alan.bate...@oracle.com >>>>>> Cc: serviceability-dev@openjdk.java.net >>>>>> Sent: Wednesday, November 20, 2013 4:11:45 PM GMT +01:00 Amsterdam / >>>>>> Berlin / Bern / Rome / Stockholm / Vienna >>>>>> Subject: Re: RFR (S): 6461635: [TESTBUG] BasicTests.sh test fails >>>>>> intermittently >>>>>> >>>>>> How about defining the class that you want to attach to as a static >>>>>> inner class to the actual test? That would give you only one file, but >>>>>> with two classes, each with its own main method and clear correlation >>>>>> between them. >>>>>> >>>>>> Mikael >>>>>> >>>>>> On 2013-11-20 15:41, Mattias Tobiasson wrote: >>>>>>> Hi, >>>>>>> Each test requires 2 files, the actual test code and a helper file. >>>>>>> >>>>>>> The helper file will launch a separate java process (called >>>>>>> Application), and then start the actual test. The actual test will then >>>>>>> attach to the Application. >>>>>>> >>>>>>> For example: >>>>>>> PermissionTests.sh: Helper file that will launch Application instance >>>>>>> and then start PermissionTest.java >>>>>>> PermissionTest.java: The actual test code that attaches to the >>>>>>> Application. >>>>>>> >>>>>>> It is the PermissionTests.sh that is started by jtreg (contains the >>>>>>> "@test"-tag). >>>>>>> >>>>>>> When I port PermissionTest.sh to java I would get 2 files called >>>>>>> PermissionTest.java, so some name change is required. >>>>>>> >>>>>>> I could have kept the old PermissionTest.java unchanged, but then I >>>>>>> would need another name for the prevoius PermissionTest.sh. And I >>>>>>> wanted a "clean" Test name for the file containing the "@test"-tag. >>>>>>> >>>>>>> I used these names: >>>>>>> TestPermission.java: Helper file. >>>>>>> TestPermissionImpl.java: Actual test code. >>>>>>> >>>>>>> I am still new to adding tests for open jdk. I am happy to change the >>>>>>> names if they do not follow the naming convention. >>>>>>> >>>>>>> Mattias >>>>>>> >>>>>>> >>>>>>> ----- Original Message ----- >>>>>>> From: alan.bate...@oracle.com >>>>>>> To: mattias.tobias...@oracle.com >>>>>>> Cc: serviceability-dev@openjdk.java.net >>>>>>> Sent: Wednesday, November 20, 2013 2:50:52 PM GMT +01:00 Amsterdam / >>>>>>> Berlin / Bern / Rome / Stockholm / Vienna >>>>>>> Subject: Re: RFR (S): 6461635: [TESTBUG] BasicTests.sh test fails >>>>>>> intermittently >>>>>>> >>>>>>> >>>>>>> Out of curiosity, what is the reason for the rename? I ask because we >>>>>>> use Basic and similar names in many areas. Also anything in the test >>>>>>> tree should be a test. >>>>>>> >>>>>>> -Alan. >>>>>>> >>>>>>> On 20/11/2013 13:47, Mattias Tobiasson wrote: >>>>>>>> Hi, >>>>>>>> Could you please review this fix. >>>>>>>> >>>>>>>> Summary of changes: >>>>>>>> >>>>>>>> 1. The real test bug fix is to add flag "-Xshare:off" when starting >>>>>>>> the "Application" instance. Without that flag, the test for >>>>>>>> ClassFileTransformer in RedefineAgent.java fails intermittently. The >>>>>>>> flag is added in function startApplication() in RunnerUtil.java. >>>>>>>> >>>>>>>> 2. Ported the following bash scripts to java: >>>>>>>> BasicTests.sh -> TestBasic.java >>>>>>>> PermissionTests.sh -> TestPermission.java >>>>>>>> ProviderTests.sh -> TestProvider.java >>>>>>>> >>>>>>>> 3. Renamed the java test code to avoid name clash with new java >>>>>>>> classes ported from bash script: >>>>>>>> BasicsTest.java -> TestBasicImpl.java >>>>>>>> PermissionTest.java -> TestPermissionImpl.java >>>>>>>> ProviderTest.java -> TestProviderImpl.java >>>>>>>> >>>>>>>> 4. Added some utility functions to jdk/testlibrary. >>>>>>>> >>>>>>>> 5. Moved exit code check from the common utility function in >>>>>>>> ProcessThread.java to the test JstatdTest.java. The check is moved to >>>>>>>> the test because other tests in the future may have other expected >>>>>>>> exit codes. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Mattias >>>>>>>> >>>>>>>> Webrev: >>>>>>>> http://cr.openjdk.java.net/~miauno/6461635/webrev.00/ >>>>>>>> >>>>>>>> Bug: >>>>>>>> https://bugs.openjdk.java.net/browse/JDK-6461635 >> >> >> -- >> Leonid Mesnik >> JVM SQE >