<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">Before we get into what API
changes are needed, let's sync on the problem first. <br>
<br>
1. CodeTransform has an `atStart` method just as it has an
`atEnd` method, and I presume overriding `atStart(builder)` is
adequate to your need. Is the issue simply that there is no
canned combinator for startHandler as there is for endHandler?
<br>
<br>
2. Adding an annotation is complicated, and we explored a
number of solutions before settling in the current place. There
are three cases:<br>
<br>
- There is no RVAA, so you have to add one<br>
- There is an RVAA, but it already has your annotation, so
there's nothing to do <br>
- There is an RVAA, and it doesn't have your annotation, so you
have to transform it<br>
<br>
(Actually there is a fourth case: it has your annotation, but
with _different properties_; there is @Foo(3) but you want to
add @Foo(4). Now what do you do? Replace it? Leave it? Add
both?)<br>
<br>
The trickiness is compounded by the fact that the latter two
cases can be handled by transforming the element for RVAA, but
the first case can't be handled until the end handler, and you
have to remember whether you saw an RVAA or not. So the process
is inherently stateful. Some options were covered in this
thread (which talked about NestMembers, but the story is the
same for annotations.)<br>
<br>
<a class="moz-txt-link-freetext" href="https://mail.openjdk.org/pipermail/classfile-api-dev/2022-August/000108.html">https://mail.openjdk.org/pipermail/classfile-api-dev/2022-August/000108.html</a><br>
<br>
Here's the recommended code for that situation:<br>
<br>
() -> new ClassTransform() {<br>
boolean foundNM = false;<br>
<br>
void accept(ClassBuilder b, ClassElement e) {<br>
switch (e) {<br>
case NestMembersAttribute a -> { transform
a; foundNM = <br>
true; }<br>
... other transform stuff ...<br>
}<br>
}<br>
<br>
void atEnd(ClassBuilder b) {<br>
if (!foundNM)<br>
builder.accept(NestMembersAttribute.of(...));<br>
}<br>
}<br>
<br>
It's irritating because you have to do three things -- keep
track of some state, rewrite an attribute if you see it, and
generate an attribute if you don't, but it's really not so
lengthy or hard to follow.<br>
<br>
I can imagine capturing this in a combinator, where you provide
two lambdas, one a transform on your favorite attribute, and one
a supplier of that attribute, but I don't think it will be that
much easier to use, it just automate managing and acting on the
boolean. <br>
<br>
<br>
<br>
</font></font><br>
<div class="moz-cite-prefix">On 3/21/2023 11:38 PM, - wrote:<br>
</div>
<blockquote type="cite" cite="mid:CABe8uE1pm2WXJ8DjB-3Hbh=85Wv5T4sVUBdsetJ4ArLcOHvoSw@mail.gmail.com">
<pre class="moz-quote-pre" wrap="">Hi,
After housekeeping the few tests after the latest integration of
additional constants in ConstantDescs, I have found two potentially
common patterns in bytecode manipulation and wish to suggest new APIs:
1. Injection of code in the beginning of methods
Currently, our CodeTransform only has an endHandler; however, this is
less useful, for a method can have multiple exit points. Usually to
track method calls, bytecode manipulation, such as those in jfr and
instrumentation, inject at the beginning of methods, which is
guaranteed to be on the code path.
Thus, I suggest a `startHandler(Consumer<CodeBuilder>)` for
CodeTransform for this purpose, instead of having to explicitly
override atStart(CodeBuilder) in non-lambda CodeTransform.
2. Adding new annotations
In ASM, annotation injection is done simply via extra annotation
visitor calls, which makes it compatible for either single or multiple
annotations. In contrast, in the Classfile API, if we want to add an
annotation, feeding a new RuntimeVisibleAnnotationAttribute will
destroy the previous RuntimeVisibleAnnotationAttribute, and handling
via a stateful ClassTransform is a bit too lengthy for users.
I don't know if we should have an API like Map::computeIfAbsent for
attributes or if we will simplify it via other means.
Chen Liang
</pre>
</blockquote>
<br>
</body>
</html>