There is a critical update, Restrict Reflective Access to Non-Global Constructors in Packages

When this critical update is enabled, regardless of API version, you can initiate only Apex classes that have a no-arguments constructor that is visible to the code running Type.newInstance.

How: This critical update enables strict enforcement of Apex type visibility rules for the Type.newInstance method. It also removes the legacy compatibility behavior supporting these rules in API version 28.0 and earlier. Apex classes contained in second-generation packages can instantiate public classes from other packages in the same namespace only if they are annotated @NamespaceAccessible.

Also, regardless of API version, construction of abstract classes or interfaces is no longer allowed even when the type is visible and can be referenced using Type.forName. Such instantiation fails with this message: "ApexType does not have a no-arg constructor" where ApexType is the type you want to create using the Type.newInstance method.

It sounds as if I should no longer be able to use Type.forName and Type.newInstance to instantiate public (non-global) classes that are inside managed packages.

However, if I activate the critical update and create an apex class with the following code and with the Salesforce.com API version set to 27.0, the code will still find and instantiate the type successfully. Though as was the case even before the critical update was enabled, Type.forName will return null if the API version is set to a newer version.

public class MyClass {
    public static void foo() {
        System.debug(Type.forName('MYNAMESPACE', 'MyPublicManagedClass').newInstance());

This also works from inside a managed package to access both unmanaged public classes and managed public classes belonging to another package, where both managed packages are 1st generation.

Is this working as expected?

  • 4
    Personally I would not rely on this even if it does work - logically it should never be possible to instantiate a managed package's public (not global) classes from outside the package. Such instantiation should have to be done in a method within the managed package. Similarly a subscriber org class should only be instantiable by managed code when that class is global.
    – Phil W
    Jul 20 '20 at 15:21
  • 4
    I will contact @ca_peterson to see if there's a known issue, or if a bug needs to be logged. If you don't have Premier Support, I'd be glad to log the case on your behalf if you can provide a package I can test with in a Sandbox.
    – sfdcfox
    Jul 20 '20 at 15:36
  • @PhilW - agreed, but there is some legacy code from before the global constraint existed / was understood. Plus probably some that was written more recently but went unnoticed because the code doing the instantiating was on an older api version so it worked anyway.
    – Jeff
    Jul 20 '20 at 15:48
  • @sfdcfox - Thank you. I do have premier support so I can file a case if this is not the intended behavior.
    – Jeff
    Jul 20 '20 at 15:52
  • 4
    I've pinged Chris Peterson, we'll have him take a look and see what he has to say about it.
    – sfdcfox
    Jul 20 '20 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.