So that projects depend on this can be published to a public artifact repository.
Note that this is not breaking backward compatibility. All codes except this file can be still compiled in Java 6.
Guava has an Automatic-Module-Name in its MANIFEST.MF now, so I believe this is not quite as important as it may seem. But if I'm mistaken, then I'd be more than happy to be proven wrong.
(BTW, I think I might have misunderstood something, because module-info.java is Java 9 specific, right? Would a Java 8 compiler (which I believe is what is used to compile guava-jre) or an Android compiler (for guava-android) happily process it or otherwise ignore it?)
Our current thinking is that we'll look into this next quarter. We have seen some problems from module-info files in third-party jars, since they're Java 9 .class files and not everyone uses Java 9 yet. So, if we can get away with Automatic-Module-Name, we'll continue to do so, possibly even beyond next quarter. But if there are cases in which Automatic-Module-Name isn't good enough, that would be good to know.
Right, thanks. We've seen problems even when the main .class files are compiled for an older version but the module-info.class is present. As I understand it, various tools try to process all .class files, and they need to be updated to ignore module-info.class.
I wasn't personally involved in fixing the problems, but the basic idea seems to be that people scan the whole classpath (using something like ClassPath.getTopLevelClasses -- which might be an example of something that needs updated to ignore module-info.class :)) and then try to examine/load the classes with a tool that understands only, say, Java 8.
@orionll Cool, thanks for confirming things for me. :)
I personally wonder how important it would be for Guava's packages to be open when used on the module path. I struggle to imagine that reflectively calling Guava's internals is a common thing to do, especially considering Guava's (IMO) pretty durn good API. 🤔
@HoldYourWaffle I think the main reason is it prevents people from using reflection to depend on internals which may change or disappear in future releases of Guava without warning.
The PR looked pretty clearly like the result of solving a dozen similar issues, so I think an extra-large jar with some -Xlint:all warnings is a pretty impressive outcome for the initial release :) (I, too, had thought that javac required you pass "real" sources along with the module-info.)
I suspect that requires would be enough to satisfy the compiler. But requires transitive seems better unless you're the kind of person who doesn't believe in requires transitive at all :)
By adding transitive you are exporting an internal package to the public. That sounds wrong to me.
I agree, maybe it is better to relocate InternalFutureFailureAccess to a public package? If com.google.common.util.concurrent.internal has never been intended to be used by lib consumers, I wouldn't even consider moving it a breaking change.
"internal" was a poor choice of package name on my part. It is actually meant to be accessible to other users. (And among the reasons that it's a poor name is that our otherinternal subpackage, the one under common.base, is not meant to be accessible to other users.) We were trying to steer "normal" users away from it, but we do want code (mainly low-level libraries and frameworks) to be able to use it to maximize performance, like here in kotlinx.coroutines. Perhaps other people have wanted to use it but been scared off by the name :(
@cpovirk Backwards-compatibility aside, the right way to go would be to rename the package and then export it.
Worse-case scenario, you could deprecate the old classes, redirect calls to the new package under the hood, and add Javadoc steering users to the new package.
The package has been around, publicly accessible, and endorsed by us for usage a few years at this point, so I think that's as good as "exported." (That includes being listed in the OSGi Export-Package line for the failureaccess jar ever since we set up OSGi there, and it includes being in the exports section of the Java module that we recently set up.) So I think it's too late to try to rename it, since that would cause the usual havoc of incompatible Guava changes.
As for the multiple releases: The main goal has been to neither add nor remove APIs. I think that 1.0.1 was to add the OSGi information, 1.0.2 was to add an Automatic-Module-Name, and 1.0.3 was to set up a proper module. It would have been idea to do that all in 1.0, but I think that the multiple releases have been only a marginal contributor to the occasional annoyances that people see with failureaccess. (But people should correct me if I'm wrong: While I hope that we don't have reason to release a 1.0.4 in the future, I would like to know both the pros and cons that such a release might have.)
Activity
jbduncan commentedon Oct 18, 2017
Guava has an
Automatic-Module-Namein itsMANIFEST.MFnow, so I believe this is not quite as important as it may seem. But if I'm mistaken, then I'd be more than happy to be proven wrong.(BTW, I think I might have misunderstood something, because
module-info.javais Java 9 specific, right? Would a Java 8 compiler (which I believe is what is used to compile guava-jre) or an Android compiler (for guava-android) happily process it or otherwise ignore it?)cpovirk commentedon Oct 18, 2017
Our current thinking is that we'll look into this next quarter. We have seen some problems from
module-infofiles in third-party jars, since they're Java 9.classfiles and not everyone uses Java 9 yet. So, if we can get away withAutomatic-Module-Name, we'll continue to do so, possibly even beyond next quarter. But if there are cases in whichAutomatic-Module-Nameisn't good enough, that would be good to know.hrchu commentedon Oct 18, 2017
It is possible to only compile
modile-info.javain Java 9, so the jar file is still compatible to users who uses earlier Java version.A maven example:
https://github.com/twonote/radosgw-admin4j/blob/java9/pom.xml#L127
cpovirk commentedon Oct 18, 2017
Right, thanks. We've seen problems even when the main
.classfiles are compiled for an older version but themodule-info.classis present. As I understand it, various tools try to process all.classfiles, and they need to be updated to ignoremodule-info.class.hrchu commentedon Oct 19, 2017
@cpovirk could you tell me more about this problem?
cpovirk commentedon Oct 19, 2017
I wasn't personally involved in fixing the problems, but the basic idea seems to be that people scan the whole classpath (using something like
ClassPath.getTopLevelClasses-- which might be an example of something that needs updated to ignoremodule-info.class:)) and then try to examine/load the classes with a tool that understands only, say, Java 8.orionll commentedon Feb 20, 2018
It's worth mentioning that if we add
module-info.java, all packages will not be open anymore.jbduncan commentedon Feb 21, 2018
@orionll Am I right to think/remember that in the JPMS, open packages are packages whose internal classes can be inspected with reflection?
orionll commentedon Feb 21, 2018
@jbduncat Yes, exactly. And also private members of public classes.
jbduncan commentedon Feb 21, 2018
@orionll Cool, thanks for confirming things for me. :)
I personally wonder how important it would be for Guava's packages to be open when used on the module path. I struggle to imagine that reflectively calling Guava's internals is a common thing to do, especially considering Guava's (IMO) pretty durn good API. 🤔
HoldYourWaffle commentedon Feb 21, 2018
Are there any reasons for it not being open? Even if it's uncommon it might still be done by some people.
jbduncan commentedon Feb 21, 2018
@HoldYourWaffle I think the main reason is it prevents people from using reflection to depend on internals which may change or disappear in future releases of Guava without warning.
184 remaining items
cpovirk commentedon Mar 28, 2025
The PR looked pretty clearly like the result of solving a dozen similar issues, so I think an extra-large jar with some
-Xlint:allwarnings is a pretty impressive outcome for the initial release :) (I, too, had thought that javac required you pass "real" sources along with themodule-info.)For JUnit 4:
Automatic-Module-Name. (That's good, as AFAIK the JUnit 4 folks are still hoping never to have to publish a release again :))requireswould be enough to satisfy the compiler. Butrequires transitiveseems better unless you're the kind of person who doesn't believe inrequires transitiveat all :)requires transitive,guava-testlibshould probably be using it for its dependency onguava, too, given thatguava-testlibusesguavatypes in its API. For that matter,guavashould probably be usingrequires transitivefor its dependency oncom.google.common.util.concurrent.internal, given thatguavauses types from that module in its API. Maybe that would eliminate the apparent need forguava-testlibto declare what would then become a redundant dependency onc.g.c.util.concurrent.internal? (I don't think that we exposejava.loggingin our API (neither inguavanorguava-testlib), at least.)Declare our module dep on `failureaccess` as `transitive`, and improv…
failureaccessastransitive, and improve module deps intestlib, too. #7748cpovirk commentedon Mar 28, 2025
Check my proposed changes here: #7748
History shows that a number of you folks know more about all this than we do :)
cowwoc commentedon Mar 28, 2025
@cpovirk I am only concerned about https://github.com/google/guava/pull/7748/files#diff-6eabd8d281c8a36ef65bc60a72f3e4af026d190937553b6b5ac0b9ddb2a6d190R20
By adding
transitiveyou are exporting an internal package to the public. That sounds wrong to me.overheadhunter commentedon Mar 28, 2025
I agree, maybe it is better to relocate
InternalFutureFailureAccessto a public package? Ifcom.google.common.util.concurrent.internalhas never been intended to be used by lib consumers, I wouldn't even consider moving it a breaking change.vietj commentedon Mar 28, 2025
@sgammon thanks for your effort
cpovirk commentedon Mar 28, 2025
Thanks for having a look.
"
internal" was a poor choice of package name on my part. It is actually meant to be accessible to other users. (And among the reasons that it's a poor name is that our otherinternalsubpackage, the one undercommon.base, is not meant to be accessible to other users.) We were trying to steer "normal" users away from it, but we do want code (mainly low-level libraries and frameworks) to be able to use it to maximize performance, like here in kotlinx.coroutines. Perhaps other people have wanted to use it but been scared off by the name :(cowwoc commentedon Mar 28, 2025
@cpovirk Backwards-compatibility aside, the right way to go would be to rename the package and then export it.
Worse-case scenario, you could deprecate the old classes, redirect calls to the new package under the hood, and add Javadoc steering users to the new package.
cowwoc commentedon Mar 28, 2025
Hmm, where is this package anyway? :) The closest I got to finding it was https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/Internal.java but this is a class, not a package.
cowwoc commentedon Mar 28, 2025
Nevermind, found it: https://github.com/google/guava/tree/master/futures/failureaccess/src/com/google/common/util/concurrent/internal
And then I found this README.md at the top-level directory:
Oops... Are we in trouble?
cpovirk commentedon Mar 29, 2025
The package has been around, publicly accessible, and endorsed by us for usage a few years at this point, so I think that's as good as "exported." (That includes being listed in the OSGi
Export-Packageline for thefailureaccessjar ever since we set up OSGi there, and it includes being in theexportssection of the Java module that we recently set up.) So I think it's too late to try to rename it, since that would cause the usual havoc of incompatible Guava changes.As for the multiple releases: The main goal has been to neither add nor remove APIs. I think that 1.0.1 was to add the OSGi information, 1.0.2 was to add an Automatic-Module-Name, and 1.0.3 was to set up a proper module. It would have been idea to do that all in 1.0, but I think that the multiple releases have been only a marginal contributor to the occasional annoyances that people see with
failureaccess. (But people should correct me if I'm wrong: While I hope that we don't have reason to release a 1.0.4 in the future, I would like to know both the pros and cons that such a release might have.)Bump `failureaccess` to 1.0.3.
failureaccessto 1.0.3. google/bazel-common#221Bump `failureaccess` to 1.0.3.