<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@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;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=EN-GB link=blue vlink="#954F72" style='word-wrap:break-word'><div class=WordSection1><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I think it’s worth comparing it to the existing approach of going through the classloader’s resource loader to obtain the class file; in cases where that worked, the class was already insecure, just in a non-obvious way. Perhaps classloaders could be given an explicit ability to control access to bytecode, and hidden classes given blanket secrecy.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I’d also like to suggest reflection APIs of other JVM languages as a use-case (at least, ones using custom attributes rather than annotations). I would have to look more into existing examples before calling it an important use-case, but something like this would have been useful for me in the past. Re: security concerns, it might be worth having a separate “access mode” for classes that you’d like to provide the bytecode of, with Code attributes stripped, for such APIs, but that could easily expand the scope of this too far from a “just expose what’s already there and possible”. </p><p class=MsoNormal><o:p> </o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm'><p class=MsoNormal style='border:none;padding:0cm'><b>From: </b><a href="mailto:brian.goetz@oracle.com">Brian Goetz</a><br><b>Sent: </b>09 February 2023 18:52<br><b>To: </b><a href="mailto:heidinga@redhat.com">Dan Heidinga</a>; <a href="mailto:gary.frost@oracle.com">Gary Frost</a><br><b>Cc: </b><a href="mailto:classfile-api-dev@openjdk.org">classfile-api-dev@openjdk.org</a><br><b>Subject: </b>Re: [External] : Re: Reflective access to bytes[] of loaded class</p></div><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal style='margin-bottom:12.0pt'><span style='font-size:13.5pt;font-family:"Courier New"'>One concern that we have is that unrestricted access to bytecode of loaded classes may constitute an attack vector for malicious code.  <br><br>While we don't recommend people program like this:<br><br>    boolean checkPassword(String pw) { <br>        return "s00perSeekrit".equals(pw);<br>    }<br><br>arbitrary access to bytecode will compromise the "security" of this code in ways that the author might not have reasonably forseen.  <br><br><br></span><o:p></o:p></p><div><p class=MsoNormal>On 2/9/2023 1:24 PM, Dan Heidinga wrote:<o:p></o:p></p></div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><div><p class=MsoNormal>Thanks for confirming, Gary.<o:p></o:p></p></div><p class=MsoNormal><o:p> </o:p></p><div><div><p class=MsoNormal>On Thu, Feb 9, 2023 at 11:59 AM Gary Frost <<a href="mailto:gary.frost@oracle.com">gary.frost@oracle.com</a>> wrote:<o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal style='margin-left:40.8pt;background:white'><span style='font-size:12.0pt;color:black'>Dan<br><br>I have indeed used JVMTI (and Java) agents for this. In the case of JVMTI by keeping a std::map<std::string,byte[]>, and providing a JNI call to get the bytes. <br><br>It works well for cases where we know the set of classes we want bytes for at JVM 'launch time' , or there is something in the class (name match? constant pool entry?) that we can trigger to prune the size of the map.    Otherwise we are forced to retain a map for all classes, just in case. <br><br>And of course who knew whether our JVMTI agent was the last 'actor' in the chain of possible mutators to play with the bytes.<o:p></o:p></span></p></div></div></div></blockquote><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Can you expand on the use case for getting the current bytes from the runtime?  As I said in the previous email, they aren't a good candidate for feeding back into the runtime due to the existing JVMTI agent process.  Is this mostly for testing purposes?<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>--Dan<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal style='mso-margin-top-alt:0cm;margin-right:0cm;margin-bottom:12.0pt;margin-left:40.8pt;background:white'><span style='font-size:12.0pt;color:black'><br><br>Hence the desire for runtime help <br><br><o:p></o:p></span></p></div><p class=MsoNormal style='margin-left:40.8pt'><img border=0 width=566 height=2 style='width:5.8916in;height:.0166in' id="Horizontal_x0020_Line_x0020_1" src="cid:image002.png@01D93CB9.25D395A0"><o:p></o:p></p><div id="m_-7567829150639208625divRplyFwdMsg"><p class=MsoNormal style='margin-left:40.8pt'><b><span style='color:black'>From:</span></b><span style='color:black'> Dan Heidinga <<a href="mailto:heidinga@redhat.com">heidinga@redhat.com</a>><br><b>Sent:</b> Thursday, February 9, 2023 4:35 PM<br><b>To:</b> Gary Frost <<a href="mailto:gary.frost@oracle.com">gary.frost@oracle.com</a>><br><b>Cc:</b> <a href="mailto:classfile-api-dev@openjdk.org">classfile-api-dev@openjdk.org</a> <<a href="mailto:classfile-api-dev@openjdk.org">classfile-api-dev@openjdk.org</a>><br><b>Subject:</b> [External] : Re: Reflective access to bytes[] of loaded class</span> <o:p></o:p></p><div><p class=MsoNormal style='margin-left:40.8pt'> <o:p></o:p></p></div></div><div><div><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p><div><div><p class=MsoNormal style='margin-left:40.8pt'>On Thu, Feb 9, 2023 at 11:03 AM Gary Frost <<a href="mailto:gary.frost@oracle.com">gary.frost@oracle.com</a>> wrote:<o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal style='margin-left:45.6pt;background:white'><span style='font-size:12.0pt;color:black'>I would like to make a case for adding a reflection API for getting the bytes for class loaded by the VM as part of this Classfile API. <o:p></o:p></span></p></div><div><p class=MsoNormal style='margin-left:45.6pt;background:white'><span style='font-size:12.0pt;color:black'><br>Something akin to <br><br>byte[] Class.getClassfileBytes();<o:p></o:p></span></p></div></div></div></blockquote><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>I've often wanted the same kind of API when doing one off tests and minor modifications so I'm very sympathetic to the request.  Typically when doing more "serious" class modification, I've used the Instrumentation::retransform API [0] or written a native JVMTI agent [1] and then such an api to get the current classfile bytes isn't required.  Does this match your typical use cases as well?<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>The JVM does some interesting handling of classfile bytes in these cases - it allows non-retransform-capable agents to do a 1 time modification of the original classfile bytes and then saves those bytes away before passing them on to the retransform-capable agents.  One subsequent retransform events, those saved bytes are reused and only the retransform-capable agents get a chance to modify the bytes.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>The reason this matters is that existing retransform-capable agents aren't expecting to see the modifications they've made present in the classfile bytes they get passed.  Providing an easy api to get the currently executing bytecodes will mean that these agents will now "see" their own modifications which may result in incompatibilities.  <o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>I'd be interested in feedback from existing major agent providers to see how much of a problem such a change would cause them before pursuing it unless there's a more common pattern of use I'm unaware of.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>[0] <a href="https://cr.openjdk.java.net/~iris/se/17/latestSpec/api/java.instrument/java/lang/instrument/Instrumentation.html#retransformClasses(java.lang.Class..">https://cr.openjdk.java.net/~iris/se/17/latestSpec/api/java.instrument/java/lang/instrument/Instrumentation.html#retransformClasses(java.lang.Class..</a>.) <o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>[1] <a href="https://cr.openjdk.java.net/~iris/se/17/latestSpec/specs/jvmti.html#RetransformClasses">https://cr.openjdk.java.net/~iris/se/17/latestSpec/specs/jvmti.html#RetransformClasses</a><o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal style='margin-left:45.6pt;background:white'><span style='font-size:12.0pt;color:black'><br><br><br>At present developers usually resort to something like <br><br>clazz.getClassLoader().getResourceAsStream(<br>    clazz.getName().replace(".", "/") + ".class")<br><br>Ignoring the fact that we may have just forced an expensive network fetch, to bytes that the JVM clearly already has 'squirrelled away' somewhere... <br><br>For me this is hugely problematic as there is no guarentee that the bytes fetched from such a stream will match the bytes that the JVM is using for the class in question.... <br><br>Java offers all sorts of opportunities (JVMTI agents, Java agents, even custom ClassLoaders) for mutating the incoming classfile's bytes. All of which the stream fetched via getResourceAsStream() completely sidesteps.<o:p></o:p></span></p></div></div></div></blockquote><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>See above (or the JVMTI spec) for which bytes get passed through to agents.  The story is more complex than it first appears.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'>--Dan<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:40.8pt'> <o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal style='margin-left:45.6pt;background:white'><span style='font-size:12.0pt;color:black'><br>This may well be considered 'out of bounds' for the Classfile API, but I think we should consider it, as it seems to be something that users of the Classfile API will need going forward. <o:p></o:p></span></p></div><div><p class=MsoNormal style='margin-left:45.6pt;background:white'><span style='font-size:12.0pt;color:black'><o:p> </o:p></span></p></div><div><p class=MsoNormal style='margin-left:45.6pt;background:white'><span style='font-size:12.0pt;color:black'>Gary<o:p></o:p></span></p></div></div></div></blockquote></div></div></div></div></div></blockquote></div></div></blockquote><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p></div></body></html>