From shade at openjdk.org Fri Jul 19 11:21:43 2024 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 19 Jul 2024 11:21:43 GMT Subject: RFR: Add utility for creating objects via factory method when unable to create via constructor In-Reply-To: References: Message-ID: On Thu, 7 Mar 2024 17:27:38 GMT, Kyle J Stiemann wrote: > Adds CLI option to provide a factory FQCN which can create objects that you want to analyze. This is useful in situations where you have dependency classes or JDK classes that require non-null objects or have other validation in the constructor. These kinds of classes can't easily be modified, so it's nice to provide an alternative option for creating them. > > For example: > > > public static final class RequiresFactory { > public RequiresFactory(final String string) { > Objects.requireNonNull(string); > if (string.isEmpty()) { > throw new IllegalArgumentException("string must not be empty"); > } > } > } > > > Usage: > > > java -jar jol-cli.jar internals --classpath my-classes.jar --factory my.Factory my.RequiresFactory > > > Where `my.Factory` is: > > > public class Factory { > public static T newInstance(Class aClass) { > > if (aClass.equals(RequiresFactory.class)) { > return aClass.cast(new RequiresFactory("test")); > } > > throw new UnsupportedOperationException(aClass.getTypeName()); > } > } Sorry, it slipped off my radar. ------------- PR Comment: https://git.openjdk.org/jol/pull/58#issuecomment-2238930302 From shade at openjdk.org Mon Jul 22 10:57:43 2024 From: shade at openjdk.org (Aleksey Shipilev) Date: Mon, 22 Jul 2024 10:57:43 GMT Subject: RFR: 7903778: JOL: Add utility for creating objects via factory method when unable to create via constructor In-Reply-To: References: Message-ID: On Thu, 7 Mar 2024 17:27:38 GMT, Kyle J Stiemann wrote: > Adds CLI option to provide a factory FQCN which can create objects that you want to analyze. This is useful in situations where you have dependency classes or JDK classes that require non-null objects or have other validation in the constructor. These kinds of classes can't easily be modified, so it's nice to provide an alternative option for creating them. > > For example: > > > public static final class RequiresFactory { > public RequiresFactory(final String string) { > Objects.requireNonNull(string); > if (string.isEmpty()) { > throw new IllegalArgumentException("string must not be empty"); > } > } > } > > > Usage: > > > java -jar jol-cli.jar internals --classpath my-classes.jar --factory my.Factory my.RequiresFactory > > > Where `my.Factory` is: > > > public class Factory { > public static T newInstance(Class aClass) { > > if (aClass.equals(RequiresFactory.class)) { > return aClass.cast(new RequiresFactory("test")); > } > > throw new UnsupportedOperationException(aClass.getTypeName()); > } > } I have only the cosmetics, really. Please go to https://github.com/stiemannkj1/jol/actions and enable workflow. It would trigger on the next commit to this PR branch. (No need to force push, the commits would be squashed on integration) jol-cli/src/main/java/org/openjdk/jol/operations/ClasspathedOperation.java line 57: > 55: OptionSpec optFactory = parser.accepts("factory", > 56: "Fully-qualified factory class name. Factory must implement a factory method with the signature: public static T newInstance(java.lang.Class)") > 57: .withRequiredArg().ofType(String.class).describedAs("factoryClass"); Suggestion: .withRequiredArg().ofType(String.class).describedAs("factory class"); jol-cli/src/main/java/org/openjdk/jol/operations/ClasspathedOperation.java line 78: > 76: > 77: if (set.has(optFactory)) { > 78: factoryClass = ClassUtils.loadClass(optFactory.value(set)); Can you check what happens if class cannot be loaded? I think it should also fall through to `printHelpOn` with some useful message? jol-cli/src/main/java/org/openjdk/jol/operations/ClasspathedOperation.java line 105: > 103: factoryClass > 104: .getMethod("newInstance", Class.class) > 105: .invoke(null, klass); The line breaks here and later are odd. We have enough column space to do: Object o = factoryClass.getMethod("newInstance", Class.class).invoke(null, klass); jol-cli/src/test/java/org/openjdk/jol/operations/ClasspathedOperationTest.java line 17: > 15: public void testTryInstantiate() throws Exception { > 16: > 17: final ClasspathedOperation classpathedOperation = new ClasspathedOperation() { Suggestion: final ClasspathedOperation op = new ClasspathedOperation() { ...and the rest of the renames. jol-cli/src/test/java/org/openjdk/jol/operations/ClasspathedOperationTest.java line 63: > 61: Objects.requireNonNull(object); > 62: } > 63: } I think it would be less confusing to clearly say this is not a factory. Current use seems to mean "requires factory", but the class name suggests this is an actual `Factory`? I think something like `NeedsFactoryObject` or something like that? jol-cli/src/test/java/org/openjdk/jol/operations/ClasspathedOperationTest.java line 71: > 69: } > 70: > 71: return null; Suggestion: } return null; jol-cli/src/test/java/org/openjdk/jol/operations/ClasspathedOperationTest.java line 77: > 75: public static final class InvalidFactory { > 76: > 77: public static T newInstance(final Class klass) { Suggestion: public static final class InvalidFactory { public static T newInstance(final Class klass) { ------------- PR Review: https://git.openjdk.org/jol/pull/58#pullrequestreview-2191226793 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686340239 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686348229 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686354459 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686356961 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686360842 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686357777 PR Review Comment: https://git.openjdk.org/jol/pull/58#discussion_r1686355300