Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Duplicate
-
1.7.x, 2.3
-
None
-
None
-
Java 17
Description
When running under Java 17 or later, introspection often picks an inaccessible method on a runtime object, which then fails when invoked.
For example, running the example below under Java 8, the output is simple:
Cert notAfter=Wed Jan 03 12:42:32 EST 2024 Test: Wed Jan 03 12:42:32 EST 2024
When running on Java 11 or later, we get:
Cert notAfter=Wed Jan 03 12:42:32 EST 2024 WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.velocity.runtime.parser.node.PropertyExecutor (file:.../velocity-engine-core-2.3.jar) to method sun.security.x509.X509CertImpl.getNotAfter() WARNING: Please consider reporting this to the maintainers of org.apache.velocity.runtime.parser.node.PropertyExecutor WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release Test: Wed Jan 03 12:42:32 EST 2024
When running on Java 17, we get:
Cert notAfter=Wed Jan 03 12:42:32 EST 2024 Exception in thread "main" org.apache.velocity.exception.VelocityException: ASTIdentifier() : exception invoking method for identifier 'notAfter' in class sun.security.x509.X509CertImpl at org.apache.velocity.runtime.parser.node.ASTIdentifier.execute(ASTIdentifier.java:282) at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:368) at org.apache.velocity.runtime.parser.node.ASTReference.render(ASTReference.java:492) at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:439) at org.apache.velocity.Template.merge(Template.java:358) at org.apache.velocity.Template.merge(Template.java:262) at CertTest.main(CertTest.java:52) Caused by: java.lang.IllegalAccessException: class org.apache.velocity.runtime.parser.node.PropertyExecutor cannot access class sun.security.x509.X509CertImpl (in module java.base) because module java.base does not export sun.security.x509 to unnamed module @45ad6cad at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392) at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674) at java.base/java.lang.reflect.Method.invoke(Method.java:560) at org.apache.velocity.runtime.parser.node.PropertyExecutor.execute(PropertyExecutor.java:149) at org.apache.velocity.util.introspection.UberspectImpl$VelGetterImpl.invoke(UberspectImpl.java:722) at org.apache.velocity.runtime.parser.node.ASTIdentifier.execute(ASTIdentifier.java:217) ... 6 more
It looks like Velocity is picking an inconvenient class on which to base its method invocation.
Here is the test source.
import java.io.OutputStreamWriter; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeServices; import org.apache.velocity.runtime.RuntimeSingleton; public class CertTest { private static final String certText = "-----BEGIN CERTIFICATE-----\n" + "MIICJTCCAaygAwIBAgIIXjahgh5+v08wCgYIKoZIzj0EAwMwaTEQMA4GA1UEBhMH\n" + "VW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4G\n" + "A1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjENMAsGA1UEAxMEdGVzdDAe\n" + "Fw0yMzEwMDUxNzQyMzJaFw0yNDAxMDMxNzQyMzJaMGkxEDAOBgNVBAYTB1Vua25v\n" + "d24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vua25vd24xEDAOBgNVBAoT\n" + "B1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xDTALBgNVBAMTBHRlc3QwdjAQBgcq\n" + "hkjOPQIBBgUrgQQAIgNiAARluamNquFohhtrjhN6Sq+QXVlb+/1GVHg0h10iDehm\n" + "msRkfPkugLIwRbLIaggzFkx66QcT4oIjhvM0Q1jM7a/9BhNUWJvZMa54M3Nh+K6P\n" + "fzp8tOGHe2EAHibDP1KSGHCjITAfMB0GA1UdDgQWBBSLy96Os2mUo7TiKAwRlEmq\n" + "dzOrCDAKBggqhkjOPQQDAwNnADBkAjBx+sqV2gzUusdOvwltH7f7sp5UtZMRFKF4\n" + "mRcGA7buAZN/YPUGgkiUZ6ZEJmw8Dn8CMEEgm8c2WTYdO/CQ5DRBbfIt1TcpiDxk\n" + "0vM+YZrSctwCJhK+3h3i4X990XvjJQ3Hmw==\n" + "-----END CERTIFICATE-----\n" ; private static final String templateText = "Test: $cert.notAfter\n"; public static void main(String[] args) throws Exception { X509Certificate cert = (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(new java.io.ByteArrayInputStream(certText.getBytes(StandardCharsets.US_ASCII))); System.out.println("Cert notAfter=" + cert.getNotAfter()); VelocityContext ctx = new VelocityContext(); ctx.put("cert", cert); VelocityEngine ve = new VelocityEngine(); ve.init(); RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices(); Template template = new Template(); template.setRuntimeServices(runtimeServices); /// For Velocity 1.7: //template.setData(runtimeServices.parse(new StringReader(templateText), "Note Template")); // For Velocity 2.x template.setData(runtimeServices.parse(new StringReader(templateText), template)); template.initDocument(); OutputStreamWriter out = new OutputStreamWriter(System.out); template.merge(ctx, out); out.flush(); } }
This fails in the same way running under both Velocity 2.3 and Velocity 1.7 (with a small required source change).
Attachments
Issue Links
- duplicates
-
VELOCITY-952 Velocity is calling the "wrong" method
- Closed