----- Mail original ----- > De: "daniel smith" <daniel.sm...@oracle.com> > À: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net> > Envoyé: Mardi 27 Octobre 2020 20:27:39 > Objet: Re: Source code analysis: calls to wrapper class constructors
>> On Oct 19, 2020, at 6:01 PM, Dan Smith <daniel.sm...@oracle.com> wrote: >> >> In the context of the Warnings for Value-Based Classes JEP, we're looking for >> usages of the deprecated wrapper class constructors ('new Integer(...)', 'new >> Double(...)', etc.). When do these get used? How often is this motivated by >> wanting a unique object vs. legacy code that has no particular reason not to >> use 'valueOf'? >> >> We've got some investigations going on at Oracle, including looking at some >> open-source projects, but I'm interested in examples from other >> companies/projects as well. Please investigate and share what you find! >> >> I'll reply in a few days with our analysis for the code we look at. > > So, some conclusions that we've drawn: > > - In 2020, the constructor calls are fairly pervasive, even in recently > released > binaries. Removing these constructors may be the most disruptive single API > change we've ever made. > > - The trend is good—serious projects have mostly responded to the deprecation > warnings introduced in 9. In 2024 (for example), the picture may be much > better. > > - It is impossible, given the current JVM model for primitive classes, for > Integer to both be a primitive class and support 'new java/lang/Integer'. > Binaries calling the deprecated constructors simply won't work. > > - There is a meaningful semantic difference, in terms of promising unique > identity, between code that does 'new Integer' and code that does > 'Integer.valueOf' or implicitly boxes. The latter is better aligned with the > class's future behavior as a primitive class. > > - Almost no usages care about the identity distinction—they just want boxing. > But it's difficult to automatically detect the usages that do. > > These points lead to the following tentative plan: > > We'll proceed as planned with deprecation for removal. The message for all > Java > programs is to stop using these constructors if you want to run in future > JDKs. > Typically, the simplest refactoring is to replace 'new Integer(x)' with just > 'x', but in some cases you might want 'Integer.valueOf(x)'. When you refactor, > you should confirm that the change in identity semantics is acceptable. > > We'll encourage IDEs to provide tooling for updating sources, including batch > processing. (As an example, IntelliJ already highlights deprecated APIs and > suggests conversions, although I'm not familiar with its batch processing > features.) > > For legacy binaries that have not been updated but that need to run on a > future > JDK, we'll provide tooling to rewrite their bytecode containing constructor > calls, either as a preprocessing step on jar files, or as a runtime > command-line argument. > > This tooling will support common bytecode patterns like 'new Foo; dup; ...; > invokespecial Foo.<init>;', but will not be a comprehensive solution. > (Mimicking the behavior of instance initialization method invocation in full > generality would be a very difficult task.) It will also carry behavioral > compatibility risks. For these reasons, it will be available as a workaround, > not as default JVM behavior. Three remarks: - the compiler can warn because a code is using new Integer(value) or warn because the compiler will automatically transform all new Integer(value) to Integer.valueOf() once Valhalla is integrated, i prefer the second solution, having a warning message saying that in the future new Integer() will not be supported and that all new Integer(...) will be transformed by the compiler automatically to Integer.valueOf(). - the introduction of the strong encapsulation in 9 was a very similar challenge, the first thing to do is to raise awareness, having a warning at runtime (so emitted by the VM) per callsite using new Wrapper(...) will help a lot. People can detect easily if they are using a dependency that use something that will not be backward compatible (this warning should be emitted by Java 16+, because there is no point to wait and because of JEP 396, there will be a second wave of people wanting to update the library they maintain, so they can fixed both issues in one pass. - IDE should inspect the jars downloaded by Maven and Gradle, and report the use of deprecated for removal APIs, again to raise awareness, a warning directly on the tag dependency in the POM saying that this dependency (or one of it's sub-dependencies) is using deprecated for removal APIs will help a lot. Rémi