<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4"><font face="monospace">After the below is integrated,
        I'd like to propose the following API changes.  <br>
        <br>
        When I reviewed the code for cached hierarchy resolvers, I was
        concerned that the cache is hidden and shared across all users,
        meaning it will continue to fill up over time.  The change
        outlined below provide half the story, which is allowing more
        control over the locus of caching.  The other half is making
        that control map easily to abstractions that users deal with.  <br>
        <br>
        What I'd like to do is move the static methods in Classfile onto
        some sort of ClassfileReaderWriter object (needs a better
        name.)  Then, the CRW becomes a sensible locus of caching, as
        well as a place to hang options.  (Yet again, something that
        seemingly made sense to be a static method at the beginning, has
        gotten complicated enough that it bites us.)<br>
        <br>
        interface ClassfileReaderWriter { <br>
            static CRW of() { ... }<br>
            static CRW of(Collection<Option> options) { ... }<br>
        <br>
            byte[] build(ClassDesc thisClass);<br>
            byte[] build(ClassDesc thisClass, Consumer<? super
        ClassBuilder> handler);<br>
            byte[] build(ClassEntry thisClassEntry,<br>
                         ConstantPoolBuilder constantPool,<br>
                         Consumer<? super ClassBuilder> handler);<br>
        <br>
            byte[] buildModule(ModuleAttribute moduleAttribute);<br>
      </font></font><font size="4"><font face="monospace">    byte[]
        buildModule(ModuleAttribute moduleAttribute, <br>
                               Consumer<? super ClassBuilder>
        handler);<br>
        <br>
      </font></font><font size="4"><font face="monospace">    // similar
        buildTo and buildModuleTo overloads<br>
        <br>
            ClassModel parse(byte[] bytes);<br>
            ClassModel parse(Path path);<br>
        }<br>
        <br>
        The CRW::of factories act as caching points for the CHR and for
        the options.  <br>
        <br>
        Additionally, I think we can simplify the options as well with
        an ADT.  Right now, we have an internal set of keys, an external
        set of factories that match up with the keys, an internal option
        carrier, and internal consumers have to blind-cast -- and we
        limit ourselves to options that have one parameter.  <br>
        <br>
        Instead, we can use a transparent ADT:<br>
        <br>
            sealed interface Option { }<br>
            record GenerateStackMaps(boolean generateMaps) implements
        Option { }<br>
            record ClassHierarchyResolver(ClassHierarchyResolver
        resolver) implements Option { }<br>
            ...<br>
        <br>
        and eliminate the factories, key enum, and internal cruft.  <br>
        <br>
        Further, breaking the limitation of "exactly one parameter"
        means we can refactor the options records to group related
        options if desired.  <br>
        <br>
      </font></font><font size="4"><font face="monospace"> </font></font>
    <div class="moz-cite-prefix">On 3/22/2023 2:55 PM, Adam Sotona
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CY4PR1001MB21503CBC6EBBFFD40D4334D98C869@CY4PR1001MB2150.namprd10.prod.outlook.com">
      
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}div.WordSection1
        {page:WordSection1;}ol
        {margin-bottom:0cm;}ul
        {margin-bottom:0cm;}</style>
      <div class="WordSection1">
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Based on the discussion in this thread I
            propose to make a first step and adjust ClassHierarchy
            factory methods following way:<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
        <ul style="margin-top:0cm" type="disc">
          <li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">ofCached(ClassHierarchyResolver resolver)<o:p></o:p></span></li>
          <li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">ofClassLoading(ClassLoader loader)<o:p></o:p></span></li>
          <li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">ofResourceParsing(ClassLoader loader)<o:p></o:p></span></li>
          <li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">ofParsing(Function<ClassDesc,
              InputStream> classStreamResolver)<o:p></o:p></span></li>
          <li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">of(MethodHandles.Lookup lookup)<o:p></o:p></span></li>
          <li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">of(Collection<ClassDesc> interfaces,
              Map<ClassDesc, ClassDesc> classToSuperClass)<o:p></o:p></span></li>
        </ul>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">So the default can be defined as:<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">DEFAULT_CLASS_HIERARCHY_RESOLVER =
ofCached(ofResourceParsing(ClassLoader.getSystemClassLoader()).orElse(ofClassLoading(ClassLoader.getSystemClassLoader())));<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Please help me to polish exact methods naming.<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Thank you,<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Adam<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
      </div>
    </blockquote>
    <br>
  </body>
</html>