Conversation
| synchronized (toJson) { | ||
| try { | ||
| toJson.setAccessible(true); | ||
| } catch (final SecurityException ex) { | ||
| throw new IllegalStateException( | ||
| "Method#setAccessible(true) is forbidden for thie method DataSource(Impl)#toJson. " | ||
| + "DataSource class: " + source.getClass().toString() | ||
| + "toJson method: " + toJson.toString(), | ||
| ex); | ||
| } | ||
|
|
||
| try { | ||
| return toJson.invoke(source); | ||
| } catch (final InvocationTargetException ex) { | ||
| final Throwable targetException = ex.getTargetException(); | ||
| if (targetException instanceof RuntimeException) { | ||
| throw (RuntimeException) targetException; | ||
| } | ||
| if (targetException instanceof Error) { | ||
| throw (Error) targetException; | ||
| } | ||
| throw new IllegalStateException("DataSource#toJson() threw unexpected Exception.", targetException); | ||
| } catch (final IllegalAccessException ex) { | ||
| throw new IllegalStateException( | ||
| "DataSource(Impl)#toJson is not accessible even after Method#setAccessible(true). " | ||
| + "DataSource class: " + source.getClass().toString() | ||
| + "toJson method: " + toJson.toString(), | ||
| ex); | ||
| } finally { | ||
| toJson.setAccessible(false); | ||
| } | ||
| } |
There was a problem hiding this comment.
Q: If we narrow the scope of toJson by obtaining a new local variable Method toJson = getToJsonMethod(source), is there a need for synchronizing and restore the accessibility here? In case there's no need, do you still consider it potentially dangerous?
There was a problem hiding this comment.
I thought it can still be dangerous because:
Method#setAccessibleis modifying the "method".- The
toJsoninstance, which is retrieved byClass#getMethod("toJson"), is expected to be the same instance if anotherClass#getMethod("toJson")is called in another thread.
Yeah, we have to consider a lot of possibility with this type of hacks -- then, as I mentioned, I'm not very positive to merge this.
| // then invoking "toJson" of "org.embulk.util.config.DataSourceImpl" caused IllegalAccessException. | ||
| // https://github.com/embulk/embulk-util-config/pull/20 | ||
| // | ||
| // Pass-through to the next step to setAccessible(true) for the "toJson" Method instance. |
There was a problem hiding this comment.
Q: I assumed a pass-through here means there's a possibility of another type of exception is thrown but could be resolved with the "accessible = true" hack?
There was a problem hiding this comment.
My thought is,
If toJson.invoke(source); throws a type of Exception:
- If the Exception is
InvocationTargetException: all rethrown to fail explicittly. - If the Exception is
IllegalAccessException: passing-through intentionally. - Otherwise: thrown-up to fail.
And those are intended and expected. The case 1 and case 3 should fail immediately. Only the case 2 should pass-through to the next step.
Then, only in the case 2, the accessible flag should be set back false by toJson.setAccessible(false); in finally.
dmikurube
left a comment
There was a problem hiding this comment.
Thanks for your comments!
| // then invoking "toJson" of "org.embulk.util.config.DataSourceImpl" caused IllegalAccessException. | ||
| // https://github.com/embulk/embulk-util-config/pull/20 | ||
| // | ||
| // Pass-through to the next step to setAccessible(true) for the "toJson" Method instance. |
There was a problem hiding this comment.
My thought is,
If toJson.invoke(source); throws a type of Exception:
- If the Exception is
InvocationTargetException: all rethrown to fail explicittly. - If the Exception is
IllegalAccessException: passing-through intentionally. - Otherwise: thrown-up to fail.
And those are intended and expected. The case 1 and case 3 should fail immediately. Only the case 2 should pass-through to the next step.
Then, only in the case 2, the accessible flag should be set back false by toJson.setAccessible(false); in finally.
| synchronized (toJson) { | ||
| try { | ||
| toJson.setAccessible(true); | ||
| } catch (final SecurityException ex) { | ||
| throw new IllegalStateException( | ||
| "Method#setAccessible(true) is forbidden for thie method DataSource(Impl)#toJson. " | ||
| + "DataSource class: " + source.getClass().toString() | ||
| + "toJson method: " + toJson.toString(), | ||
| ex); | ||
| } | ||
|
|
||
| try { | ||
| return toJson.invoke(source); | ||
| } catch (final InvocationTargetException ex) { | ||
| final Throwable targetException = ex.getTargetException(); | ||
| if (targetException instanceof RuntimeException) { | ||
| throw (RuntimeException) targetException; | ||
| } | ||
| if (targetException instanceof Error) { | ||
| throw (Error) targetException; | ||
| } | ||
| throw new IllegalStateException("DataSource#toJson() threw unexpected Exception.", targetException); | ||
| } catch (final IllegalAccessException ex) { | ||
| throw new IllegalStateException( | ||
| "DataSource(Impl)#toJson is not accessible even after Method#setAccessible(true). " | ||
| + "DataSource class: " + source.getClass().toString() | ||
| + "toJson method: " + toJson.toString(), | ||
| ex); | ||
| } finally { | ||
| toJson.setAccessible(false); | ||
| } | ||
| } |
There was a problem hiding this comment.
I thought it can still be dangerous because:
Method#setAccessibleis modifying the "method".- The
toJsoninstance, which is retrieved byClass#getMethod("toJson"), is expected to be the same instance if anotherClass#getMethod("toJson")is called in another thread.
Yeah, we have to consider a lot of possibility with this type of hacks -- then, as I mentioned, I'm not very positive to merge this.
|
Hi Dai, I understood. Please see this discussion as a sidetrack one and prioritize the other three. It's just interesting to me to discuss on this one out. |
This is where I think I misaligned: IIUC,
Pretty much the same idea as the above, I thought different calls to getMethod returns different metadata instances? (I'm trying to evaluate the "hacki-ness" of this one and weighing the trade-off of having a hard-to-spot bug when this combination of Embulk and embulk-util-config is met (I totally agree that this rarely will happen)). |
|
Hmm, not sure why this pull-request is closed... |
|
Reopening. |
AFAIU yes, but actually, not 100% confident. Maybe not. But anyway, the Javadoc does not clearly describe that point. https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean- Also, the specification may change. For instance, Java 11 (or 12?) changed |
As described in #24, this pull-request is to save a case of :
embulk-util-config:0.1.4or earlier.But, as reviewers can see, this is too hacky, and dangerous potentially. In addition, this is not a critical issue when all the plugins are using
embulk-util-config:0.2.1+with #24.I basically believe we don't need this although I made this pull-request. (So, this is not included in the Milestone v0.2.1 as of now.)
Wondered if I could have a comment from reviewer(s).